使用传递给方法的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
可以隐式转换为)