2011-01-31 2 views
9

Tôi có một phương pháp:Có sử dụng một biểu thức lambda được chuyển vào một phương thức làm chậm truy vấn khung Entity Framework không?

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

tôi tái cơ cấu phương pháp để làm cho nó tổng quát hơn để tôi có thể vượt qua trong một Func vì vậy mà tôi có thể xác định tuyên bố where và những gì bất động sản từ bảng Bars được giao cho MyObject.Prop như thế này:

public static void GetObjectsV2(Func<Bar, bool> whereFunc, Func<Bar, string> 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 dường như chạy chậm hơn nhiều so với GetObjects. Có bất kỳ lý do nào mà điều này sẽ ảnh hưởng đến hiệu năng hay không và nếu có thì có cách nào để giải quyết vấn đề này trong khi vẫn giữ chức năng linh hoạt không?

Trả lời

16

Lý do nó chạy chậm hơn là vì bạn đang chuyển vào một Func<Bar, bool> buộc buộc bối cảnh truy xuất TẤT CẢ Bars và sau đó chạy Func trên tập kết quả trả về. Một cách để làm cho hoạt động này tốt hơn là để vượt qua trong Expression<Func<Bar, bool>>

Đưa rằng tất cả lại với nhau sẽ cho kết quả như sau:

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

Cảm ơn rất nhiều cho câu trả lời nhanh chóng! – aubreyrhodes

5

Như I discovered in my own question, .Where(o => whereFunc(o)) là không giống như .Where(whereFunc) trong khung Entity.

Đầu tiên, .Where(Expression<Func<Bar, bool>>) hoạt động giống như bất kỳ cuộc gọi linq nào khác, chỉ cần thêm biểu thức vào cây biểu thức.

Trong trường hợp thứ hai, .Where(Func<Bar, bool>>), nó sẽ biên dịch và đánh giá cuộc gọi LINQ (cho đến thời điểm này chỉ là context.Bars) trước khi áp dụng biến vị ngữ whereFunc.


Vì vậy, để trả lời câu hỏi của bạn, câu hỏi thứ hai chậm hơn nhiều vì nó kéo toàn bộ bảng Bars vào bộ nhớ trước khi thực hiện bất kỳ thứ gì với nó. Sử dụng .Where(o => whereFunc(o)) thay vì nên khắc phục điều đó

(hoặc, như Mark gợi ý, thay đổi loại whereFunc để Expression<Func<Bar, bool>>, mà Func<Bar, bool> là mặc nhiên chuyển đổi thành)