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

时间:2013-01-22 09:58:27

标签: c# linq entity-framework

我写了一些参数化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”。更容易创建一个函数。 这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

变体形式

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

方法2 :这是执行EF查询的正确方法,因为EF会根据Expression tree构建实际查询。当您编写.Where时,它可能与方法1相同,但这是不同的。

IQueryable扩展方法正在使用Expression trees,因此您可以(或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来执行此操作,例如因为该对象不包含这些信息。

答案 1 :(得分:0)

不确定这是否适用,但是你看一下编译的查询:Compiled Queries (LINQ to Entities)这会导致更高效的SQL语句