使用传递给方法的lambda表达式是否会降低entity framework查询的速度?

我有一个方法:

public static void GetObjects() { using(MyContext context = new MyContext()) { var objects = context.Bars.Where(b => b.Prop1 != null) .Select(b => new MyObject{Prop = b.Prop1, Name = b.Name}) .ToList(); foreach(var object in objects) { // do something with the object } } } 

我重构了方法,使其更通用,以便我可以传入一个Func以便我可以指定where语句和Bars表中的哪些属性被分配给MyObject.Prop如下所示:

 public static void GetObjectsV2(Func whereFunc, Func selectPropFunc) { using(MyContext context = new MyContext()) { var objects = context.Bars.Where(whereFunc) .Select(b => new MyObject{Prop = selectPropFunc(b), Name = b.Name}) .ToList(); foreach(var object in objects) { // do something with the object } } } 

GetObjectsV2似乎比GetObjects运行得慢得多。 是否有任何原因会影响性能,如果有,有什么方法可以保持function的灵活性吗?

它运行速度较慢的原因是因为你传入了一个Func ,它强制上下文重新执行所有Bars,然后在返回的结果集上运行Func。 一种使这种运行更好的方法是传入Expression>

将所有这些放在一起将导致以下结果:

 public static void GetObjectsV2(Expression> whereFunc, Expression> selectPropFunc) { using(MyContext context = new MyContext()) { var objects = context.Bars.Where(whereFunc) .Select(selectPropFunc) .ToList(); foreach(var object in objects) { // do something with the object } } } 

正如我在自己的问题中发现的那样 , .Where(o => whereFunc(o))与entity framework中的.Where(whereFunc)

第一个, .Where(Expression>)与任何其他linq调用一样,只需将表达式附加到表达式树。

在第二种情况下, .Where(Func>) ,在应用whereFunc谓词之前,它将编译和评估linq调用(到目前为止只是context.Bars )。


所以,为了回答你的问题,第二个问题要慢得多,因为它在对它做任何事情之前将整个Bars表拉入内存。 使用.Where(o => whereFunc(o))代替应该修复它

(或者,正如Mark建议的那样,将whereFunc的类型更改为Expression> ,其中Func可以隐式转换为)