MSDN documentation odnosi się do tego pytania w sekcji odroczonego wykonywania zapytań (podkreślenie moje).
W kwerendy, która zwraca ciąg wartości, zmienna zapytania sama nigdy nie przechowuje wyniki kwerendy i tylko przechowuje zapytaniu poleceń. Wykonanie zapytania jest odroczona aż zmiennej zapytania się powtórzyć w ciągu foreach lub pętli For Each ...
To zawęża odpowiedź wariantów 2 i 3.
foreach
jest po prostu cukier syntaktyczny, pod kompilatorem ponownie zapisuje to jako pętlę while. Istnieje dość dokładne wyjaśnienie, co się stanie here. Zasadniczo pętla zakończy się patrząc coś takiego
{
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 jest zaawansowany, zanim osiągnie swój kod wewnątrz pętli, to tak lekko, zanim pojawi się @item.Bar
.Pozostaje tylko opcja 2, linia @foreach (var item in Model)
(choć technicznie ta linia nie istnieje po kompilacji z twoim kodem).
Nie jestem pozwany, jeśli zapytanie zostanie wykonane podczas połączenia z numerem GetEnumerator()
lub pierwszym wywołaniem e.MoveNext()
.
Jak @pst zwraca uwagę w komentarzach, istnieją inne sposoby, aby wywołać wykonanie zapytania, takie jak wywołując ToList
, a to nie może wewnętrznie użyć foreach
pętlę. MSDN dokumentacja rodzaju rozwiązuje ten here:
IQueryable interfejs dziedziczy interfejs IEnumerable tak, że jeśli reprezentuje kwerendy, wyniki tej kwerendy mogą być wymienione. Wyliczenie powoduje wykonanie drzewa wyrażeń skojarzonego z obiektem IQueryable . Definicja "wykonywania drzewa wyrażenia " jest specyficzna dla dostawcy zapytań. Na przykład może to obejmować tłumaczenie drzewa wyrażeń na odpowiedni język zapytania dla bazowego źródła danych. Kwerendy, które nie zwracają wyliczalnych wyników są wykonywane po wywołaniu metody Execute.
Moje zrozumienia, że jest to próba wyliczyć wyrażenia spowoduje to wykonać (czy to poprzez foreach
lub jakiś inny sposób). Jak dokładnie to się stanie zależy od implementacji dostawcy.
Po prostu chcę wspomnieć, że prawdopodobnie należy wymusić wykonanie w kontrolerze. Zapobiegnie to problemom w przyszłości, jak przypadkowe wielokrotne wyliczanie go. – Dharun
Nie sądzę, że jest to świetny pomysł - co, jeśli widok nie potrzebuje wszystkich danych, np. Jeśli jest siatka z przywoływaniem: jeśli wymuszasz wykonanie, tracisz zalety tego stronicowania –
To jest coś, na co należy uważać podczas pracy z EntityFramework. Po raz pierwszy zauważyłem to zachowanie, ponieważ obiekty były leniwie załadowane w widoku, którego nie tylko nie potrzebowałem, ale faktycznie łamało pewne reguły biznesowe. Skończyło się na dodaniu filtru do odłączania obiektów od menedżera stanu po zakończeniu wykonywania kontrolera, aby upewnić się, że odroczone wykonanie w widoku zwróci wartość null w leniwych właściwościach ładowania i nie wyda dodatkowych wywołań db. Coś, na co trzeba uważać ... – macsux