Was macht Include () in LINQ?

93

Ich habe versucht, viel zu recherchieren, aber ich bin eher ein DB-Typ - daher macht selbst die Erklärung im MSDN für mich keinen Sinn. Kann jemand bitte erklären und einige Beispiele dafür geben, was die Include()Aussage im Begriff der SQLAbfrage bewirkt ?

CJ
quelle
Sehr einfach, ich kenne nur einfache Select, Where, Order by, einige aggregierte Gegner. Ich habe weder JOIN in LINQ noch Include ausprobiert. Mein letztendliches Ziel war es, diese LINQ-Abfragen in SQL umschreiben zu können
CJ

Antworten:

165

Angenommen, Sie möchten eine Liste aller Ihrer Kunden erhalten:

var customers = context.Customers.ToList();

Nehmen wir an, dass jedes CustomerObjekt einen Verweis auf seine Menge von Ordershat und dass jedes OrderVerweise Verweise hat, auf LineItemsdie auch a verweisen kann Product.

Wie Sie sehen können, kann die Auswahl eines Objekts der obersten Ebene mit vielen verwandten Entitäten zu einer Abfrage führen, bei der Daten aus vielen Quellen abgerufen werden müssen. Mit dieser Option Include()können Sie als Leistungsmaß angeben, welche verwandten Entitäten als Teil derselben Abfrage aus der Datenbank gelesen werden sollen.

Wenn Sie dasselbe Beispiel verwenden, werden möglicherweise alle zugehörigen Auftragskopfzeilen eingefügt, jedoch keiner der anderen Datensätze:

var customersWithOrderDetail = context.Customers.Include("Orders").ToList();

Als letzter Punkt, seit Sie nach SQL gefragt haben, könnte die erste Anweisung ohne Include()eine einfache Anweisung generieren:

SELECT * FROM Customers;

Die letzte Anweisung, die aufgerufen wird, Include("Orders")könnte folgendermaßen aussehen:

SELECT *
FROM Customers JOIN Orders ON Customers.Id = Orders.CustomerId;
Yuck
quelle
1
Danke dir. Mit Ihrem Beispiel kann ich sagen , wenn ich das auch möchte schließen LineItemsund Productsdie LINQ - Abfrage sollte wie folgt aussehen: var customersWithOrderDetail = context.Customers.Include("Orders").Include("LineItems").Include("Products").ToList();?
CJ
2
Ja, Sie können mehrere Aufrufe verketten Include(), um Objekte entlang unterschiedlicher "Pfade" zu erfassen. Wenn Sie Objekte im selben Pfad möchten, müssen Sie nur einen Aufruf ausführen, der den gesamten Pfad angibt. Da LineItemsund Productskeine Pfadkomponenten gemeinsam nutzen, benötigen Sie separate Aufrufe.
Yuck
Ist die Verwendung von Include obligatorisch? Ich bin mir ziemlich sicher, dass ich an Lösungen gearbeitet habe, bei denen ich verwandte Objekte erhalten konnte, ohne sie zu verwenden.
Jepzen
@Jepzen Es hängt davon ab, ob Sie faul geladene Entitäten verwenden oder nicht.
Yuck
@Juck, ich glaube, dies funktioniert, wenn Sie Lazy-Loading verwenden. Im Falle eines eifrigen Ladens müssen Sie keine "include" -Anweisung verwenden, aber dies führt definitiv zu Leistungsproblemen. Bitte korrigieren Sie mich diesbezüglich.
Sam
26

Ich wollte nur hinzufügen, dass "Include" Teil des eifrigen Ladens ist. Es wird im Entity Framework 6-Lernprogramm von Microsoft beschrieben. Hier ist der Link: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/reading-related-data-with-the -entity-Framework-in-einer-Asp-Net-MVC-Anwendung


Auszug aus der verlinkten Seite:

Es gibt verschiedene Möglichkeiten, wie das Entity Framework verwandte Daten in die Navigationseigenschaften einer Entität laden kann:

Faules Laden. Beim ersten Lesen der Entität werden verwandte Daten nicht abgerufen. Wenn Sie jedoch zum ersten Mal versuchen, auf eine Navigationseigenschaft zuzugreifen, werden die für diese Navigationseigenschaft erforderlichen Daten automatisch abgerufen. Dies führt zu mehreren Abfragen, die an die Datenbank gesendet werden - eine für die Entität selbst und eine jedes Mal, wenn verwandte Daten für die Entität abgerufen werden müssen. Die DbContext-Klasse aktiviert standardmäßig das verzögerte Laden.

Eifriges Laden. Wenn die Entität gelesen wird, werden verwandte Daten zusammen mit ihr abgerufen. Dies führt normalerweise zu einer einzelnen Join-Abfrage, die alle benötigten Daten abruft. Mit der IncludeMethode legen Sie das eifrige Laden fest .

Explizites Laden. Dies ähnelt dem verzögerten Laden, außer dass Sie die zugehörigen Daten explizit im Code abrufen. Dies geschieht nicht automatisch, wenn Sie auf eine Navigationseigenschaft zugreifen. Sie laden verwandte Daten manuell, indem Sie den Objektstatus-Managereintrag für eine Entität abrufen und die Collection.Load-Methode für Sammlungen oder die Reference.Load-Methode für Eigenschaften aufrufen, die eine einzelne Entität enthalten. (Im folgende Beispiel, wenn Sie die Administrator - Navigationseigenschaft laden wollen, dann würden Sie ersetzen Collection(x => x.Courses)mitReference(x => x.Administrator) .) In der Regel würden Sie expliziten Laden nur verwenden , wenn Sie verzögertes Laden ausgeschaltet haben.

Da die Eigenschaftswerte nicht sofort abgerufen werden, werden sowohl das verzögerte Laden als auch das explizite Laden auch als verzögertes Laden bezeichnet.

Minoosha
quelle
2
Willkommen bei SO =) Nur ein Vorschlag, aber wenn Sie so etwas beantworten, fügen Sie, wenn Sie können, ein Code-Snippet hinzu. Links können leider tot sein.
The_Cthulhu_Kid
2

Stellen Sie sich vor, Sie erzwingen das Eager-Laden in einem Szenario, in dem Ihre Unterelemente ansonsten verzögert geladen würden.

Die Abfrage, die EF an die Datenbank sendet, führt zunächst zu einem größeren Ergebnis. Beim Zugriff werden jedoch keine weiteren Abfragen beim Zugriff auf die enthaltenen Elemente durchgeführt.

Ohne diese Funktion würde EF jedoch später separate Abfragen ausführen, wenn Sie zum ersten Mal auf die Unterelemente zugreifen.

robkrueger
quelle