Wird LINQ lazy-evaluiert?

8

Grüße, ich habe folgende Frage. Ich habe die genaue Antwort nicht gefunden und es ist sehr interessant für mich. Angenommen, ich habe den folgenden Code, der die Datensätze aus der Datenbank abruft (z. B. um sie in eine XML-Datei zu exportieren).

%Vor%

Angenommen, es gibt eine Million Datensätze, die die Bedingung where im Code erfüllen. Was wird passieren? Alle diese Daten werden von SQL Server sofort in den Runtime-Speicher abgerufen, wenn sie das foreach -Konstrukt erreichen, oder sie werden dann abgerufen, dann der erste Datensatz, der zweite. Mit anderen Worten: Läuft LINQ wirklich mit der Situation bei der Iteration durch große Sammlungen (siehe mein posten hier für Details)?

Wenn nicht, wie werden die Speicherprobleme in diesem Fall gelöst? Wenn ich wirklich die große Sammlung durchqueren muss, was soll ich tun? Berechnen Sie mit Hilfe der Count-Funktion die tatsächliche Anzahl der Elemente in der Sammlung und lesen Sie anschließend die Daten aus der Datenbank in kleinen Teilen. Gibt es eine einfache Möglichkeit, Paging mit LINQ Framework zu implementieren?

    
SPIRiT_1984 04.02.2011, 12:46
quelle

4 Antworten

8

Alle Daten werden gleichzeitig von SQL Server abgerufen und in den Speicher geladen. Der einzige Weg, den ich mir vorstellen kann, ist die Verarbeitung von Daten in kleineren Blöcken (wie die Seite mit Skip () und Take ()). Aber das erfordert natürlich mehr Treffer für SQL Server.

Hier ist eine Linq Paging-Erweiterung Methode, die ich dafür geschrieben habe:

%Vor%     
Randy Minder 04.02.2011, 12:51
quelle
4

Ja, LINQ verwendet eine faule Auswertung. Die Datenbank würde abgefragt werden, wenn die foreach gestartet wird, aber sie würde alle Daten auf einmal abrufen (es wäre viel weniger effizient, Millionen von Abfragen für jeweils nur ein Ergebnis gleichzeitig auszuführen).

Wenn Sie Bedenken haben, zu viele Ergebnisse auf einmal zu erzielen, können Sie Skip und Top verwenden, um nur eine begrenzte Anzahl von Ergebnissen gleichzeitig zu erhalten (also Ihr Ergebnis paginieren).

    
alex 04.02.2011 12:51
quelle
1

Es wird abgerufen, wenn Sie ToList oder ähnliche Methoden aufrufen. LINQ hat die Ausführung aufgeschoben:

Der Weg - selbst bei einer verzögerten Ausführung und dem Laden der gesamten Sammlung aus einer Datenquelle im Fall eines OR / M oder eines anderen LINQ-Anbieters - wird vom Implementierer der LINQ-Objektquelle bestimmt.

Das ist zum Beispiel, dass einige OR / M Lazy-Loading bereitstellen können, und das bedeutet, dass Ihre "gesamte Kundenliste" so etwas wie ein Cursor und Zugriff auf eines der Elemente (ein Mitarbeiter) und eine Eigenschaft ist. lädt nur den Mitarbeiter selbst oder die aufgerufene Eigenschaft.

Aber wie auch immer, das sind die Grundlagen.

EDIT: Jetzt sehe ich, dass es eine LINQ-to-SQL-Sache ist ... Oder ich weiß nicht, ob der Autor von Frage LINQ missverstanden hat und er weiß nicht, dass LINQ nicht LINQ-zu-SQL ist, aber es ist mehr ein Muster und eine Sprachfunktion.

    
Matías Fidemraizer 04.02.2011 12:53
quelle
0

OK, jetzt dank dieser Antwort Ich habe eine Idee - wie über das Mischen der Funktion einer Seite mit Rendite Möglichkeiten? Hier ist ein Beispielcode:

%Vor%

Ich denke, auf diese Weise können wir das Speicherproblem überwinden, aber die Syntax von foreach nicht so kompliziert machen.

    
SPIRiT_1984 04.02.2011 13:11
quelle

Tags und Links