LINQ EF Core 3.0中的重大更改。使用表达式

时间:2019-11-26 10:59:20

标签: linq .net-core entity-framework-core .net-core-3.0 entity-framework-core-3.0

在我的应用中,我有一些查询使用相同的重复逻辑:

var someThings = context.table1
  .where(SomeLogic)
  .ToList();

使用EF Core 2.1,我可以将这些逻辑封装在具有所有这些表达式的层中:

public static Expression<Func<MyObject, bool>> SomeLogic =>
            myObject => myObject.CreationDate.Date == DateTime.Now.Date
                    && (myObject.Whatever.HasValue || myObject.MoreWhatever);

现在我发现它正在内存中进行评估,这很糟糕。

如果我做类似的事情:

var someThings = context.table1
  .where(myObject => 
      myObject.CreationDate.Date == DateTime.Now.Date
      && (myObject.Whatever.HasValue || myObject.MoreWhatever))
  .ToList();

然后在数据库中评估查询,但是我在错误的层中放入了一些逻辑。

我尝试用功能或任何其他工具替代Expression,但我找不到解决方法。

是否可以像以前一样将查询的逻辑封装在一个层中,但是保留EF规则,以便仍可以在数据库中评估此查询?

谢谢。

1 个答案:

答案 0 :(得分:2)

为什么需要一个“真实”表达式,而不仅仅是Lambda is explained in this answer。创建的表达式可以在任何地方创建,并作为参数传递给执行查询的函数。

此答案应指导您的操作方式。您只需要用what.hasvalue ... stuff

替换两个伪表达式即可。
var param = Expression.Parameter(typeof(MyObject), nameof(MyObject));

//    myObject.CreationDate.Date == DateTime.Now.Date
Expression dateExpression = Expression.Equal(Expression.Constant(DateTime.Now),
    Expression.PropertyOrField(param, "CreationDate"));


var dummyExpression1 = Expression.Equal(Expression.Constant(1), Expression.Constant(1));
var dummyExpression2 = Expression.Equal(Expression.Constant(1), Expression.Constant(1));

//    && (myObject.Whatever.HasValue || myObject.MoreWhatever)
Expression orExpression = Expression.Or(dummyExpression1, dummyExpression2);


Expression allConditions = Expression.And(dateExpression, orExpression);

//myObject =>
Expression myExpression = Expression.Lambda<Func<MyObject, bool>>(allConditions, param);

var someThings = context.table1
    .where(myExpression)
    .ToList();

我对Expression.PropertyOrField的麻烦最大。如果您具有嵌套结构,则需要遍历数据结构并调用Expression.PropertyOrField,第一个参数是上一次调用Expression.PropertyOrField的结果。