EF Core 3.0 中的 LINQ 重大更改。使用表达式
LINQ Breaking changes in EF Core 3.0. Using expressions
在我的应用程序中,我有一些使用相同重复逻辑的查询:
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 规则以便仍然可以在数据库中评估此查询?
谢谢。
为什么需要 "real" 表达式而不仅仅是 Lambda is explained in this answer。创建的表达式可以在任何地方创建,并作为参数传递给执行查询的函数。
这个答案应该可以指导您前进的方向。您只需将两个虚拟表达式替换为 whatever.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.
的结果
在我的应用程序中,我有一些使用相同重复逻辑的查询:
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 规则以便仍然可以在数据库中评估此查询?
谢谢。
为什么需要 "real" 表达式而不仅仅是 Lambda is explained in this answer。创建的表达式可以在任何地方创建,并作为参数传递给执行查询的函数。
这个答案应该可以指导您前进的方向。您只需将两个虚拟表达式替换为 whatever.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.
的结果