MSDN documentation giải quyết câu hỏi này trong phần thực thi truy vấn bị trì hoãn (phần nhấn mạnh của tôi).
Trong truy vấn trả về một chuỗi giá trị, biến truy vấn chính nó không bao giờ chứa kết quả truy vấn và chỉ lưu trữ truy vấn lệnh. Thực hiện các truy vấn được hoãn lại cho đến khi biến truy vấn được lặp qua trong một foreach hoặc cho mỗi vòng lặp ...
Đó thu hẹp câu trả lời cho lựa chọn 2 và 3.
foreach
chỉ là cú pháp đường, bên dưới trình biên dịch viết lại như là một vòng lặp while. Có một lời giải thích khá kỹ lưỡng về những gì xảy ra here. Về cơ bản vòng lặp của bạn sẽ kết thúc tìm kiếm một cái gì đó giống như
{
IEnumerator<?> e = ((IEnumerable<?>)Model).GetEnumerator();
try
{
int m; // this is inside the loop in C# 5
while(e.MoveNext())
{
m = (?)e.Current;
// your code goes here
}
}
finally
{
if (e != null) ((IDisposable)e).Dispose();
}
}
Enumerator này là tiên tiến trước khi nó đạt mã của bạn bên trong vòng lặp, nên hơi trước khi bạn có thể @item.Bar
.Điều đó chỉ để lại tùy chọn 2, dòng @foreach (var item in Model)
(mặc dù về mặt kỹ thuật, dòng đó không tồn tại sau khi trình biên dịch được thực hiện với mã của bạn).
Tôi không kiện nếu truy vấn sẽ thực hiện trên cuộc gọi đến GetEnumerator()
hoặc trên cuộc gọi đầu tiên đến e.MoveNext()
.
Như @pst chỉ ra trong các ý kiến, có những cách khác để kích hoạt thực thi một truy vấn, chẳng hạn như bằng cách gọi ToList
, và nó có thể không trong nội bộ sử dụng một vòng lặp foreach
. MSDN tài liệu loại địa chỉ này here:
Giao diện IQueryable thừa hưởng giao diện IEnumerable để nếu nó đại diện cho một truy vấn, kết quả của truy vấn có thể được liệt kê. Điều tra khiến cây biểu thức được liên kết với một đối tượng IQueryable được thực hiện. Định nghĩa "thực thi biểu thức cây" là cụ thể cho nhà cung cấp truy vấn. Ví dụ: có thể liên quan đến việc dịch cây biểu thức sang ngôn ngữ truy vấn thích hợp cho nguồn dữ liệu cơ bản. Các truy vấn không trả về số đếm được thực thi khi phương thức Execute được gọi.
hiểu biết của tôi về điều đó là một nỗ lực để liệt kê các biểu hiện sẽ gây ra nó để thực thi (có thể là thông qua một foreach
hoặc một số cách khác). Làm thế nào chính xác điều đó xảy ra sẽ phụ thuộc vào việc thực hiện các nhà cung cấp.
Tôi chỉ muốn đề cập rằng bạn có lẽ nên buộc thực hiện trong bộ điều khiển. Điều này sẽ ngăn chặn các vấn đề trong tương lai như vô tình liệt kê nó nhiều lần. – Dharun
Tôi không nghĩ rằng đó là một ý tưởng tuyệt vời - nếu xem không cần tất cả dữ liệu, ví dụ: nếu lưới của nó có phân trang: nếu bạn buộc thực hiện, bạn sẽ mất các lợi ích của phân trang –
Đây là điều cần phải cẩn thận khi làm việc với EntityFramework. Lần đầu tiên tôi nhận thấy hành vi này bởi vì các đối tượng đã nhận được tải lười biếng trong quan điểm, mà không chỉ tôi không cần, nhưng đã thực sự vi phạm quy tắc kinh doanh nhất định. Tôi đã kết thúc việc thêm một bộ lọc để tách các đối tượng khỏi trình quản lý trạng thái sau khi thực hiện điều khiển hoàn thành để đảm bảo rằng việc thực thi hoãn lại trong khung nhìn sẽ trả về null trên các thuộc tính tải lười và không phát ra các cuộc gọi db bổ sung. Một cái gì đó để xem ra cho ... – macsux