开发者

Does using a lambda expression passed into a method slow down an Entity Framework query?

开发者 https://www.devze.com 2023-02-07 23:12 出处:网络
I have a method: public static void GetObjects() { using(MyContext context = new MyContext()) { var objects = context.Bars.Where(b => b.Prop1 != null)

I have a method:

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
         }
    }
}

I refactored the method to make it more general so that I can pass in a Func so that I can specify the where statement and what property from the Bars table gets assigned to MyObject.Prop like this:

public static void GetObjectsV2(Func<Bar, bool> whereFunc, Func<Bar, string> selectPropFunc)
{
    using(MyContext context = new MyContext())
    {
         var objects = context.Bars.Where(whereFunc)
  开发者_StackOverflow社区                     .Select(b => new MyObject{Prop = selectPropFunc(b), Name = b.Name})
                       .ToList();
         foreach(var object in objects)
         {
             // do something with the object
         }
    }
}

GetObjectsV2 seems to run much slower than GetObjects. Are there any reasons this would affect performance, and if so, are there any ways around this while still keeping the function flexible?


The reason it is running slower is because you are passing in a Func<Bar, bool> which forces the context to retrive ALL Bars and then run the Func on the returned result set. A way to make this run better is to pass in Expression<Func<Bar, bool>>

Putting that all together will result in the following:

public static void GetObjectsV2(Expression<Func<Bar, bool>> whereFunc, Expression<Func<Bar, string>> 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
         }
    }
}


As I discovered in my own question, .Where(o => whereFunc(o)) is not the same as .Where(whereFunc) in the Entity Framework.

The first one, .Where(Expression<Func<Bar, bool>>) works like any other linq call, simply appending the expression to the expression tree.

In the second case, .Where(Func<Bar, bool>>), it will compile and evaluate the linq call (which so far is just context.Bars) before applying the whereFunc predicate.


So, to answer your question, the second one is much slower because it is pulling the entire Bars table into memory before doing anything with it. Using .Where(o => whereFunc(o)) instead should fix that

(or, as Mark suggests, change the type of whereFunc to Expression<Func<Bar, bool>>, which Func<Bar, bool> is implicitly convertible to)

0

精彩评论

暂无评论...
验证码 换一张
取 消