2016-08-08 7 views
1

Ich las this answer und ich erkannte, dass mir nicht klar ist, wie eifrig Laden im In-Memory-Lebenszyklus einer IQueryable funktioniert.Ruft die eifrige Include-Funktion Daten im Speicher auf?

Sagen Sie bitte db.Customers.Include("Orders") haben, die ein Objekt Diagramm wie folgt erzeugt:

Customer 
    Order 
    Order 
    Order 

Wenn Sie aufzählen nicht die Rückkehr von einem Include hat er die Daten im Speicher laden?

Das heißt,

IQueryable<Customer> customersWithOrders = db.Customers.Include("Orders"); 

implizieren, dass die Customer Sammlung (und seine Orders) wurde im Speicher durch das mit Spannung enthalten Orders gebracht? Oder bedeutet "Begierde", dass, wenn die Customer Auflistung aufgezählt wird, die Aufträge ebenfalls in den Speicher gebracht werden?

Antwort

2

Hier passiert zwei Dinge. Zuerst wird keine Abfrage an die Datenbank gesendet, bis eine Operation ausgeführt wurde, die die Ausführung dieser Abfrage erfordert. Wenn Sie beispielsweise Folgendes tun würden:

var foos = db.Foos.Where(...); 

Es wurde noch keine Abfrage ausgegeben. Wenn Sie dann jedoch etwas tun würden wie:

foreach (var foo in foos) 
{ 
    ... 
} 

Dann wird die Abfrage an die Datenbank gesendet. Andere Dinge, die dazu führen, dass die Abfrage ausgeführt wird, sind Dinge wie das Aufrufen von ToList(), Count(), usw. Grundsätzlich, wann immer ein Bedarf an den tatsächlichen Daten besteht, und dann sendet Entity Framework die Anfrage.

Dann gibt es das völlig separate Konzept von eifrig vs Lazy Loading. Dies ist ungefähr bezogenen Elemente und ist im Grunde darüber, ob Entity Framework einen oder mehrere Joins als Teil der Abfrage oder nicht. Mithilfe von Include() weisen Sie Entity Framework an, einen Join für diese Beziehung auszustellen. Auch hier wird keine Abfrage ausgegeben, bis sie ausgewertet wird (Iteration, Aufzählung, Anzahl usw.), aber wenn Sie sie evaluieren, werden sowohl die Menge von Entitäten als auch die von Ihnen eingeschlossenen Entitäten alle gleichzeitig gezogen.

Wenn Sie keine Beziehung einschließen, dann greifen Sie auf Lazy-Loading zurück, was bedeutet, dass die Beziehung nicht materialisiert wird, wenn Sie nicht auf irgendeine Weise darauf zugreifen. Dies ähnelt in gewisser Hinsicht der Funktionsweise der ursprünglichen Abfrage. Die zugehörigen Elemente werden nur an dem Punkt abgerufen, an dem die Daten tatsächlich benötigt werden. Andernfalls wird keine Abfrage ausgegeben.Dies ist jedoch eine völlig separate Abfrage.

Lang und kurz, Sie müssen nur darauf achten, welche Daten Sie wann benötigen. Wenn Sie verwandte Entitäten verwenden möchten, sollten Sie diese einschließen , bevor die Abfrage ausgewertet wird, aber in beiden Fällen wird die Abfrage nur gesendet, wenn die Daten, die es darstellt, erforderlich sind.

2

Eager Loading ändert nur die zugrunde liegende Abfrage. Das ist auch der Grund, warum Sie mehrere Aufrufe von Include() verketten können (wie auch andere LINQ-Aufrufe, die sich auf die verzögerte Ausführung von LINQ stützen).

Nur bei der Aufzählung werden die Daten explizit von der Datenquelle angefordert.

Update (per @Ehsan Sajjad Kommentar):

Mit Lazy-Loading, auch wenn die Abfrage bereits materialisiert worden (eine foreach oder ToList() zum Beispiel verwendet wird), die Navigations Eigenschaft (Order in Dieser Fall wird nur beim Zugriff auf die Datenquelle angefordert.

+0

Was ist der Unterschied dann b/w eifrig und faul? –

Verwandte Themen