2010-10-28 40 views
6

Tôi đã có truy vấn LINQ tải một hệ thống phân cấp các đối tượng như sau.EF Ở đâu (x => x.ColumnVal == 1) vs FirstOrDefault (x => x.Column == 1)

Query # 1

var result = db.Orders 
       .Include("Customer") 
       // many other .Include() here 
       .FirstOrDefault(x => x.Customer.CustomerId == 1 && 
            x.OrderId == orderId); 

Tôi đã có MAJOR vấn đề hiệu suất với nó.
Mức sử dụng CPU gần 100% và mức sử dụng bộ nhớ rất cao.

Và tôi đã chỉnh sửa nó thành vấn đề sau và sự cố hiệu suất đã được khắc phục.

Query # 2

var result = db.Orders 
       .Include("Customer") 
       // many other .Include() here 
       .Where(x => x.Customer.CustomerId == 1 && 
          x.OrderId == orderId) 
       .FirstOrDefault(); 



Tôi chỉ muốn xác nhận sự nghi ngờ của tôi.
Query # 1 có lẽ là vòng lặp qua tất cả hồ sơ của tôi trong bộ nhớ tìm kiếm một bản ghi tương ứng
vs
Query # 2 lọc các hồ sơ trên cơ sở dữ liệu và sau đó nhận được kỷ lục đầu tiên mà thôi.

Đó có phải là lý do tại sao Truy vấn # 1 có vấn đề về hiệu suất?

Để an toàn, tôi có cần sử dụng số .Select(x => x) trước .FirstOrDefault() không?

Query # 3

var result = db.Orders 
       .Include("Customer") 
       // many other .Include() here 
       .Where(x => x.Customer.CustomerId == 1 && 
          x.OrderId == orderId) 
       .Select(x => x) 
       .FirstOrDefault(); 
+0

Tôi đồng ý với những suy nghĩ ban đầu của bạn. Quan sát các truy vấn được tạo ra và đặt tâm trí của bạn để nghỉ ngơi :-) –

Trả lời

3

Không, cả hai đều nên kết quả trong một truy vấn SQL tương tự khi được thực thi. Bạn có thể chứng minh nó bằng cách xem xét SQL Profiler và xem SQL chính xác được gửi từ EF trong cả hai trường hợp. Tối ưu hóa hiệu suất của bạn phải do một số yếu tố khác gây ra. Đây là lý do tại sao:

Bao gồm phương thức trả về một ObjectQuery<T>:

public class ObjectQuery<T> : ObjectQuery, IOrderedQueryable<T>, 
           IQueryable<T>, IEnumerable<T>, 
           IOrderedQueryable, IQueryable, 
           IEnumerable, IListSource 

Có nghĩa FirstOrDefault nó phương pháp đi kèm với 2 quá tải:

// Defined by Enumerable: 
FirstOrDefault(Func<T, Boolean>) 

// Defined by Queryable: 
FirstOrDefault(Expression<Func<T, Boolean>>) 

Khi bạn mã .FirstOrDefault(x => x.Customer.CustomerId == 1 trình biên dịch sẽ đi vào một quá trình được gọi là Độ phân giải quá tải để suy ra loại biểu thức lambda x => x.Customer.CustomerId == 1 vì nó có thể chuyển đổi thành loại tham số của cả hai loại quá tải.
Trình biên dịch sẽ sử dụng thuật toán (mà tôi vẫn đang cố gắng tìm trong Đặc tả ngôn ngữ C#!), tìm ra rằng việc chuyển đổi lambda thành Expression<Func<T, Boolean>chuyển đổi tốt hơn hơn là Func<T, Boolean> để chọn quá tải IQueryable.
Do đó, bạn sẽ thấy vị từ trong SQL được tạo khi quan sát nó trong SQL Profiler.

+0

Hi Morteza, bạn đã trả lời một câu hỏi tương tự một chút khác nhau nhưng nói với anh ta để bao gồm "using System.Linq.Expressions;". Tôi không có câu nói đó. Đó có phải là lý do tôi gặp vấn đề về hiệu năng không? http://stackoverflow.com/questions/3540410/ef-4-0-weird-behaviour-of-firstordefault-method/3540477#3540477 – stun

+0

Cảm ơn bạn đã nhắc nhở điều đó. Tôi đồng ý, nó khác, nhưng tôi vẫn nhấn mạnh vào câu trả lời mới của tôi ở đây và tôi cập nhật câu trả lời của mình để cho thấy lý do tại sao. Hãy chạy cả hai và xem kết quả trong Profiler, bạn sẽ thấy rằng cả hai kết quả trong cùng một SQL chính xác và xin vui lòng cho tôi biết nếu nó không. –

0

Tôi đã tìm ra thủ phạm. Đó là truy vấn SQL SQL được tạo bởi Entity Framework.
Tôi có một Schema phức tạp với rất nhiều mối quan hệ nhiều-nhiều.

Entity Framework đã tạo ra một 32.000 dòng dài chuỗi SQL:. '(
Bây giờ, tôi đang thay đổi mã của tôi để tải các hệ thống cấp bậc bằng tay đối với một số phần

Xin vui lòng cho tôi biết nếu có ai biết một số tốt bài viết để đọc về các mối quan hệ Eager Loading và Many-to-Many

0

Tôi nghĩ tốt nhất là nên sử dụng ... Ở đâu (condition) .Take (1) .FirstOrDefault() vì Take (1) có thể dễ dàng dịch sang SQL dưới dạng mệnh đề TOP. Bất kỳ ai với tôi?

+0

FirstOrDefault() sẽ tự động tạo truy vấn với TOP của SQL (1) – Bertm13

Các vấn đề liên quan