为什么单独实例化的Func <T,bool>谓词不会转换为带有Entity Framework的SQL?

Eoi*_*ell 2 sql linq entity-framework generic-function ef-code-first

我有一个EF Code First Db上下文,我用它来查询数据库.我在Func<Product, bool>从我的Aggregate Repository 传入查询时发现了一些性能问题,并且进一步调查结果发现查询没有被转换为SQL查询.

经过一番挖掘,我发现了以下内容.

var results = _context.Products
            .Where(p => p.ProductCode.Contains("AAA"))
            .Where(p => p.CategoryId == 1)
            .ToList();
Run Code Online (Sandbox Code Playgroud)

这完全符合预期.它使用Where子句生成一些参数化SQL.

================================================== ================

var results2 = _context.Products
            .Where(p => p.ProductCode.Contains("AAA") && p.CategoryId == 1)
            .ToList();
Run Code Online (Sandbox Code Playgroud)

这也按预期工作.它生成与上面相同的sql

================================================== ================

Func<Product, bool> pred = (p => p.ProductCode.Contains("AAA") && p.CategoryId == 1);

var results3 = _context.Products.Where(pred).ToList();
Run Code Online (Sandbox Code Playgroud)

这打破了.它不会在SQL中生成where子句,它会返回所有内容,然后在代码中对其进行过滤.

ang*_*son 5

因为为了转换成SQL,它必须是一个Expression<...>,而不是一个Func<...>.

这是由编译器自动完成的,由于Linq-to-SQL类的重载需要表达式而不是委托,编译器会自动将代码(看起来像lambda或匿名方法)转换为表达式对象并通过.

但是,如果你自己负责构建函数,编译器就不能这样做,而且Linq-to-SQL不采用匿名方法,它只需要表达式.

你可以做的是执行你可以查询的部分,然后通过你的函数过滤结果,但我会考虑只是将值的类型更改为表达式.