如何在实体框架中参数化 Linq 查询或 Lambda 查询

本文关键字:查询 Linq Lambda 参数 实体 框架 | 更新日期: 2023-09-27 17:55:12

我写了一些参数化 Lambda 查询

        //Method 1:
        Func<SalesOrderLineEntity, bool> func01 = (o => o.SOLNumber == "123456");
        var q01 = _context.SalesOrderLineEntities.Where(func01).ToList();
        //Got the result, but SQLServer Read All Records to memory before "where"
        //Method 2:
        Expression<Func<SalesOrderLineEntity, bool>> exp02 = (o => o.SOLNumber == "123456");
        var q02 = _context.SalesOrderLineEntities.Where(exp02).ToList();
        //Got the result,Exec "Where" in SQLServer
        //Method 3:
        Expression<Func<SalesOrderLineEntity, bool>> exp03 = (o => func01(o));
        var q03 = _context.SalesOrderLineEntities.Where(exp03.Compile()).ToList();
        //Same to Method 1,because Compile() result is Func<SalesOrderLineEntity, bool>
        //Method 4:
        var q04 = _context.SalesOrderLineEntities.Where(exp03).ToList();
        //Error:The LINQ expression node type 'Invoke' is not supported in LINQ to Entities

方法1和3:效率很低方法4:错误

方法2:需要我通过lambda构建一个表达式。我觉得这很难,因为我会用到很多"if,else",更容易创建一个函数。正确的方法是什么?

如何在实体框架中参数化 Linq 查询或 Lambda 查询

变体

方法 1:EF 从数据库读取所有记录,因为您将Func传递到 Where 子句中,这不是正确的候选项:EF 无法从中提取生成查询所需的信息,它只能在内存中集合上使用该函数。

方法

2:这是执行 EF 查询的正确方法,因为 EF 基于Expression tree构建实际查询。当您编写.Where时,它可能看起来像方法 1 相同,但这是不同的。

IQueryable 扩展方法使用表达式树,因此您可以(或 EF 可以)在运行时计算该信息。

方法

3:这本质上与方法 1 相同,因为您编译了表达式。这是使用它们时的一个关键区别:表达式包含构建实际操作的信息,但这不是操作本身。你需要在之前编译它(或者例如,你可以基于它们生成 SQL 查询,这就是 EF 的工作方式)。

方法 4:EF 无法将func01()调用转换为任何 SQL 函数。它无法翻译任何类型的代码,因为它需要等效的 SQL 操作。你可以尝试使用通用方法,你会得到相同的结果,这与 Func 无关。

这里发生了什么?

如果我们简化底层流程,那么上面的答案可能会更清晰。

//Method 2:
Expression<Func<SalesOrderLineEntity, bool>> exp02 = (o => o.SOLNumber == "123456");
var q02 = _context.SalesOrderLineEntities.Where(exp02).ToList();
//Got the result,Exec "Where" in SQLServer

EF 可以读取以下内容(通过表达式):

  • 用户希望使用Where进行筛选
  • 这是一个表达式,让我们获取一些信息
  • 好吧,它需要SalesOrderLineEntity,我有该类型的映射
  • 表达式告知属性SOLNumber必须等于"123456"
  • 好的,我有一个SOLNumber的映射,所以很好
  • 我可以将相等运算符转换为等效的 SQL 运算符
  • 一切正常,因此我们可以构建SQL查询

当然,您不能使用Func来执行此操作,例如,因为该对象不包含这些信息。

不确定这是否适用,但您是否查看了编译的查询: 编译查询(LINQ to Entities),这应该会产生更高效的 SQL 语句