2016-06-30 6 views
2

Ich habe über Lazy Loading von dieser Website gelesen. Enable or disable LazyLoadingEntity Frame Arbeit Lazy Loading aktiviert Bedeutung

„Wenn wir eine Liste von Studenten fordern mit Lazy Loading aktiviert ist, wird der Datenanbieter alle unsere Studenten von der DB erhalten, aber jede StudentAddress Eigenschaft wird nicht geladen, bis die Eigenschaft explizit zugegriffen wird.“

Diese Aussage besagt, dass wenn ich Lazy Loading Enabled = true setze die zugehörigen Daten nicht geladen werden. Jedoch

Wenn ich Lazy Loading aktiviert = True den obigen Code zurückgibt alle Stundenten mit ihren Lehrern und Adresse. Was ist der Punkt, den ich hier vermisse? Bitte könnte jemand es erklären?

+0

LazyLoading lädt einfach die Daten, wenn es (in linq Begriffen) gemeint ist, anstatt es auf das Objekt zu laden, egal ob es ausgegeben wird oder nicht. Das obige Beispiel würde Adressen langsam laden, wenn Sie sagten: foreach (var student in stdList) {@ stdList.Address.City}. Im Allgemeinen sollten Sie sich von LazyLoading fernhalten, da dies zu einem n + 1-Szenario führen kann, in dem Sie Ihren Datenbankserver mit Anfragen bombardieren. – BlackjacketMack

Antwort

1

Egal welche Einstellung Sie haben, wenn Sie .ToList() verwenden, wird es "aufzählbar". Dies ist sehr signifikant, und dieser Satz sollte allgemein bekannt werden.

Wenn .ToList() verwendet wird, treten viele Dinge auf. Das Aufzählen des Aufzählungsbezeichners bedeutet, dass der vorherige Satz zum Aufzählen des Satzes jetzt verwendet wird, um die Menge tatsächlich zu durchlaufen und die Daten aufzufüllen. Das bedeutet, dass der vorherige Enumerator (der intern als Ausdrucksbaum gespeichert wurde) nun von Entity Framework an Ihre SQLProvider Factory gesendet wird. Dadurch wird das Objektdiagramm aus dem Ausdrucksbaum in SQL konvertiert und die Abfrage auf dem Server ausgeführt, wodurch die Daten zurückgegeben und die Liste aufgefüllt wird.

Lazy laden anstelle von ToList() wäre, wenn Sie diese IQueryable aufzählbar hätte, und dann iteriert, dass manuell jedes Element in der Menge oder nur Teilelemente in der Menge geladen.

Sobald Sie die Liste der zurückgegebenen Elemente haben, wird Lazy Loading nur zum Spielen kommen, wenn Navigationseigenschaften vorhanden sind. Wenn es verwandte Eigenschaften gibt, z. B. wenn Sie eine Rechnung haben und die zugehörigen Kundeninformationen aus der Kundentabelle abrufen möchten. Die Beziehung wird nicht explizit zuerst zurückgegeben, nur die Rechnungen. Um also die Kundendaten zu erhalten, könnte man dann (während der Kontext noch offen war, d. H. Nicht entsorgt wurde) über die .Customer Referenz auf Ihr Objekt zugreifen und es laden. Um umgekehrt alle Kunden während der ursprünglichen Enumeration zu laden, könnten Sie die .Include()-Funktionalität für Ihre Abfrage verwenden, und dies würde dann der SQL-Provider-Factory mitteilen, eine Verknüpfung zu verwenden, wenn die Abfrage ausgegeben wird.


In Ihrem speziellen Beispiel

List<Students> stdList = Datacontext.Students.ToList(); 

Dies wird von allen Lehrern und Adressen tatsächlich nicht Last unabhängig davon, ob ein träges Laden aktiviert ist oder nicht. Es lädt nur die Studenten. Wenn Sie ein Lehrer zu faul Last wollen, während die Datacontext ist noch nicht angeordnet sind, können Sie dann verwenden

var firstStudent = stdList.First(); 
var teacher = firstStudent.Teacher; 
//and at this point lazy loading will fetch the teacher 
//by issuing **another** query (round trip) to the database 

Das wäre nur möglich, wenn ein träges Laden aktiviert waren.


Die Alternative dazu ist zu eifrig Last, die würde die Lehrer und Adressen enthalten. Das würde so aussehen

List<Students> stdList = Datacontext.Students 
    .Include(s => s.Teacher) 
    .Include(s => s.Address).ToList(); 

Und dann später, wenn Sie einen Lehrer des Kontext zuzugreifen versuchen sind entsorgt werden könnte und Zugang wäre noch möglich, weil die Daten bereits geladen wurden.

1

Wie haben Sie festgestellt, dass die Eigenschaft geladen wurde, mit dem Debugger? Wenn das der Fall ist, haben Sie bereits die Antwort. Mit dem Debugger greifen Sie auch auf diese Eigenschaft zu, wodurch auch das Lazy Loading ausgelöst wird.

Wie funktioniert das?

Wenn Ihre Entitäten meets diese Anforderungen erfüllen, erstellt EF eine Proxyklasse für jede Ihrer Entitäten, die Change Tracking oder Lazy Loading unterstützt. Auf diese Weise können Sie die zugehörigen Entitäten nur laden, wenn auf diese zugegriffen wird. Wie ich bereits erläutert habe, wird der Debugger auch das verzögerte Laden auslösen.

Nun seien Sie vorsichtig mit Lazy Loading, sobald Sie Kontext freigegeben haben, erhalten Sie eine Ausnahme, wenn Sie versuchen, Zugriff auf eine der verwandten Eigenschaften zu erhalten. Also würde ich vorschlagen, in diesem Fall eager loading zu verwenden.

+0

Sollte ich Lazy Loading Enabled = false setzen oder nicht eifrig laden? – Blast

+0

Wenn Sie eifrig laden verwenden, dann kann eine gute Idee sein, lazy loading zu deaktivieren, mache ich das in meinen Projekten, um mich zu zwingen, explizit zu schreiben, dass ich eine verwandte Eigenschaft laden möchte, aber Sie können mit beiden arbeiten. – octavioccl