2010-04-20 32 views
9

này hoạt động:Tại sao LINQ-to-Entites nhận ra phương thức tùy chỉnh của tôi?

Entities.WorkOrderSet.Where(MyCustomMethod); 

này không:

Entities.WorkOrderSet.Where(o => MyCustomMethod(o)); 

([Chỉnh sửa] Ngay cả khi không new, nó không hoạt động)

Tôi hiểu lý do tại sao thứ hai không hoạt động - nhưng tại sao thế giới lại làm việc đầu tiên !? Tôi không nên nhận được một "LINQ-to-Entities không nhận ra phương thức ..." khi chạy, như với lần thứ hai?

Để tham khảo, đây là MyCustomMethod

public bool MyCustomMethod(WorkOrder workOrder) 
{ 
    return !workOrder.WorkOrderNum.StartsWith("A", StringComparison.CurrentCultureIgnoreCase); 
} 

Sử dụng EF1, không EF4

+0

Bạn nhận được ngoại lệ nào khi bạn cố chạy ứng dụng thứ hai? –

+0

Ngoài ra .. bạn có chắc chắn EF không chỉ nhận được toàn bộ bảng và chạy các chức năng cục bộ khi bạn chạy shippet đầu tiên của bạn? Chạy trình lược tả SQL và kiểm tra truy vấn nào được gửi đến máy chủ? –

+0

Tôi nhận được "LINQ-To-Entities không thể nhận ra phương thức ..." - đây là hành vi mong đợi, vì các phương thức tùy chỉnh không thể được dịch sang SQL. Việc sửa lỗi thông thường là gọi .ToList() trước ... nhưng vì một lý do nào đó, nó có vẻ hoạt động mà không có điều đó! –

Trả lời

6

đầu tiên làm việc vì nó là một phương pháp mở rộng và là đang thực hiện các truy vấn như một func, và sau đó lọc danh sách của bạn see here. Vì vậy, nói chung nó sẽ tự động cast nơi để

Where(Func<WorkOrder, bool> 

Thứ hai không vì nó đang đẩy nơi tuyên bố của bạn xuống đến db. Khi biểu thức lambda được đánh giá nó được mở rộng như thế này:

Where(Expresion<Func<WorkOrder, bool>>) 

Đây là một tốt article giải thích Expressions vs Func

Here is another SO post that helps to explain the difference

[Chỉnh sửa (BlueRaja)]

Bản chỉnh sửa mới này có vẻ chính xác. Để làm rõ: có vẻ như Func<WorkOrder, bool> hoàn toàn có thể truyền tới Expression<Func<WorkOrder, bool>>, nhưng không phải là cách khác.

Có quá tải Where cho cả hai loại. .Where(MyCustomMethod) đang gọi số Func<WorkOrder, bool>, trong khi .Where(o => MyCustomMethod(o)) đang gọi số Expression<Func<WorkOrder, bool>>.

+1

Hãy kiểm tra lại .. Anh ấy có thể đang sử dụng một lớp ẩn danh, nhưng phương thức tùy chỉnh của anh ấy sẽ vẫn nhận được đối tượng WorkOrder làm tham số, trong khi mã của bạn thậm chí sẽ không biên dịch :) –

+0

Có lẽ tôi nên xây dựng (xem chỉnh sửa ở trên): mã biên dịch, nhưng nó không thành công khi chạy * "LINQ to Entities không nhận ra phương thức ..." * Ví dụ: http://blog.dreamlabsolutions.com/post/2008/11/17/LINQ-Method- không thể được dịch thành một cửa hàng-expression.aspx Điều này được mong đợi, nhưng thực tế là DOES đầu tiên làm việc là bất ngờ! –

+0

@Nix nhìn lại: P mới {WorkOrder = o} thực sự là một lớp ẩn danh ... Bên trong .Where (o => ...) o là lớp ẩn danh .. Trong khi o.WorkOrder thuộc loại WorkOrder .. trong trường hợp đó tham số được truyền vào hàm của anh ta là đúng loại! –

1

Chỉ cần hình thành này là một "câu trả lời" ở đây, thay vì một lời nhận xét ..

Tôi nghĩ rằng đây là một tính năng mới trong .NET 4, nơi khuôn khổ nhận ra rằng chức năng này không thể được dịch sang SQL, nhưng có thể được xử lý dễ dàng trong bộ nhớ. Vì vậy, nó sẽ lấy toàn bộ tập dữ liệu tới máy cục bộ và tiếp tục xử lý truy vấn ..

Điều đầu tiên là khi bạn dịch sang cây biểu thức, sẽ trực tiếp nói rằng nó chạy một phương thức bên ngoài, trong khi đoạn thứ hai của bạn là không phải "trực tiếp". Tôi cho rằng đây là lý do tại sao trong trường hợp đầu tiên L2E có thể dễ dàng hiểu những gì đang diễn ra, và quyết định làm gì, trong trường hợp thứ hai nó "nghĩ" tốt hơn là gửi ngoại lệ và để các nhà phát triển gãi đầu của họ thêm^_^

+0

Sử dụng EF1, có nghĩa là .Net 3.5 –

+0

có thể đó là một điều EF1 và L2S 1 sau đó? Hoặc có lẽ đó là một tính năng đã có mặt trong một thời gian? Bất kể nó là gì - giải thích tốt nhất tôi có thể đưa ra là khung công tác đang cố gắng thông minh, dựa trên cây biểu thức mà truy vấn của bạn được biên dịch thành :) –

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