为什么EntityFramework的LINQ解析器以不同的方式处理外部定义的谓词?

Joe*_*ett 9 .net c# linq entity-framework sql-generation

我正在使用Microsoft的Entity Framework作为ORM,我想知道如何解决以下问题.我想ProductProducts集合中获得Product.StartDate比当今更大的对象.(这是整个问题的简化版本.)

我目前使用:

var query = dbContext.Products.Where(p => p.StartDate > DateTime.Now);
Run Code Online (Sandbox Code Playgroud)

执行此操作时,在使用ToList()例如查询后,它可以正常工作,并且创建的SQL是有效的:

SELECT * FROM Product WHERE StartDate > (GetDate());
Run Code Online (Sandbox Code Playgroud)

但是,我想将谓词移动到一个函数以获得更好的可维护性,所以我尝试了这个:

private Func<Product, bool> GetFilter()
{
  Func<Product, bool> filter = p => p.StartDate > DateTime.Now;
  return filter;
}
var query = dbContext.Products.Where(GetFilter());
Run Code Online (Sandbox Code Playgroud)

这也是从代码的角度来看,只要它返回相同的Product集合,但这次创建的SQL类似于:

SELECT * FROM Product;
Run Code Online (Sandbox Code Playgroud)

筛选器从SQL Server移动到客户端,使其效率降低.

所以我的问题是:

  • 为什么会发生这种情况,为什么LINQ解析器会以不同的方式处理这两种格式?
  • 我可以做些什么来利用过滤器分离但在服务器上执行它?

And*_*ber 8

您需要使用Expression<Func<Product, bool>>它才能使其像您想要的那样工作.普通Func<Product, bool>告诉LINQ你希望它Where在你的程序中运行MSIL而不是SQL.这就是为什么SQL会拉入整个表,然后你的.NET代码在整个表上运行谓词.


Nuf*_*fin 4

您正在返回一个Func,但要将谓词注入到 SQL 中,LINQ 需要表达式树。如果您将方法(当然还有局部变量)的返回类型更改为Expression<Func<Product, bool>>.