Giả sử tôi có biểu thức IQueryable<T>
mà tôi muốn đóng gói định nghĩa, lưu trữ và sử dụng lại hoặc nhúng nó vào truy vấn lớn hơn sau đó. Ví dụ:Làm cách nào để duy trì hoạt động trì hoãn LINQ?
IQueryable<Foo> myQuery =
from foo in blah.Foos
where foo.Bar == bar
select foo;
Bây giờ tôi tin rằng tôi chỉ có thể giữ đối tượng myQuery đó xung quanh và sử dụng nó như tôi đã mô tả. Nhưng một số điều tôi không chắc chắn về:
Tốt nhất để tham số hóa nó? Ban đầu tôi đã xác định điều này trong một phương thức và sau đó trả lại
IQueryable<T>
là kết quả của phương thức. Bằng cách này tôi có thể xác địnhblah
vàbar
làm đối số phương pháp và tôi đoán nó chỉ tạo ra mộtIQueryable<T>
mới mỗi lần. Đây có phải là cách tốt nhất để đóng gói logic của mộtIQueryable<T>
? Có cách nào khác không?Điều gì sẽ xảy ra nếu truy vấn của tôi phân giải thành vô hướng thay vì
IQueryable
? Ví dụ: nếu tôi muốn truy vấn này chính xác như được hiển thị nhưng thêm.Any()
để cho tôi biết nếu có bất kỳ kết quả nào khớp với? Nếu tôi thêm(...).Any()
thì kết quả làbool
và được thực hiện ngay lập tức, đúng không? Có cách nào để sử dụng các toán tửQueryable
này (Any
,SindleOrDefault
, v.v.) mà không thực thi ngay lập tức không? LINQ-to-SQL xử lý điều này như thế nào?
Edit: Phần 2 thực sự thêm về cố gắng tìm hiểu sự khác biệt giới hạn giữa IQueryable<T>.Where(Expression<Func<T, bool>>)
vs IQueryable<T>.Any(Expression<Func<T, bool>>)
là gì. Có vẻ như sau này không linh hoạt khi tạo các truy vấn lớn hơn, nơi thực thi sẽ bị trì hoãn. Các Where()
có thể được nối thêm và sau đó các cấu trúc khác có thể được thêm vào sau đó và cuối cùng được thực thi. Kể từ khi Any()
trả về giá trị vô hướng, có vẻ như nó sẽ thực thi ngay lập tức trước khi phần còn lại của truy vấn có thể được xây dựng.
Nghe giống như # 1, có phương pháp về cơ bản xây dựng một 'IQueryable' mới mỗi lần là một điều tốt * vì cách này tôi sẽ không gặp vấn đề với việc xử lý. Trong # 2, tôi đã nhầm lẫn về cách LINQ-to-SQL có thể dịch toán tử 'Any', nhưng tôi không thể trì hoãn. Nếu tôi sử dụng toán tử 'Any' trong một truy vấn lớn hơn thì nó sẽ được thực thi ngay lập tức ở đó, hay nó là một phần của việc thực hiện truy vấn lớn hơn? – mckamey
OK Tôi nghĩ tôi gần như ở đó. Nếu tôi đã nhúng một '.Any()' vào một mệnh đề 'where' thì nó sẽ không thực hiện điều đó trong một vòng lặp, đúng không? Nó sẽ biên dịch thành biểu thức SQL thích hợp và gửi nó xuống. Vì vậy, trong thực tế, nó không phải là '.Any()' ngăn cản việc thực hiện trì hoãn vì nó được sử dụng như thế nào. Về cơ bản nếu kết quả của một truy vấn * toàn bộ là một vô hướng thì các số liệu của trình biên dịch bạn cần kết quả bây giờ thay vì tiếp tục xây dựng một 'IQueryable'. –
mckamey
@McKAMEY đúng, ngay khi bạn sử dụng. Bất kỳ() trong một ngữ cảnh không bị trì hoãn thì nó sẽ thực thi. Trong trường hợp của .Where() nó đang tìm kiếm một biểu thức, đó là trì hoãn, vì vậy bạn đang ok. Trong trường hợp của var hoặc vòng lặp foreach, những nguyên nhân gây ra bởi vì họ không phải là deferrable. – Joseph