Frage

Angesichts der folgenden LINQ to SQL-Abfrage:

var test = from i in Imports
           where i.IsActive
           select i;

Die interpretierte SQL-Anweisung lautet:

SELECT [t0].[id] AS [Id] .... FROM [Imports] AS [t0] WHERE [t0].[isActive] = 1

Angenommen, ich wollte in der Auswahl eine Aktion ausführen, die nicht in SQL konvertiert werden kann.Nach meinem Verständnis besteht der herkömmliche Weg, dies zu erreichen, darin, dies zu tun AsEnumerable() Dadurch wird es in ein funktionsfähiges Objekt umgewandelt.

Angesichts dieses aktualisierten Codes:

var test = from i in Imports.AsEnumerable()
           where i.IsActive
           select new 
           { 
               // Make some method call 
           };

Und aktualisiertes SQL:

SELECT [t0].[id] AS [Id] ... FROM [Imports] AS [t0] 

Beachten Sie das Fehlen einer where-Klausel in der ausgeführten SQL-Anweisung.

Bedeutet das, dass die gesamte Tabelle „Importe“ im Speicher zwischengespeichert wird?Würde dies die Leistung überhaupt verlangsamen, wenn die Tabelle eine große Menge an Datensätzen enthalten würde?

Helfen Sie mir zu verstehen, was hier tatsächlich hinter den Kulissen passiert.

War es hilfreich?

Lösung

Der Grund für AsEnumerable ist zu

Assenumerable (TSource) (iEnumerable (tSource)) kann verwendet werden, um zwischen Abfrageimplementierungen zu wählen, wenn eine Sequenz IEnumerable (T) implementiert, aber auch einen anderen Satz öffentlicher Abfragemethoden aufweist

Als Sie also angerufen haben Where Methode zuvor haben Sie eine andere aufgerufen Where Methode aus der IEnumerable.Where.Das Where Die Anweisung war für die Konvertierung von LINQ in SQL, das neue Where ist der IEnumerable einer, der einen braucht IEnumerable, zählt es auf und liefert die passenden Elemente.Das erklärt, warum Sie sehen, dass verschiedene SQL-Anweisungen generiert werden.Die Tabelle wird vorab vollständig aus der Datenbank übernommen Where Die Erweiterung wird in Ihrer zweiten Version des Codes angewendet.Dies könnte zu einem ernsthaften Engpass führen, da sich die gesamte Tabelle im Speicher befinden muss oder, schlimmer noch, die gesamte Tabelle zwischen Servern übertragen werden müsste.Erlauben Sie dem SQL-Server die Ausführung Where und tun, was es am besten kann.

Andere Tipps

an der Stelle, an der die Aufzählung durchgelastet wird, wird die Datenbank dann abgefragt und das gesamte resulteset abgerufen.

Eine Teil- und Teillösung kann der Weg sein.Betrachten

generasacodicetagpre.

sagen wir auch, dass das NondatabaseconvertAlecriterion Feld C vom Ergebnis erfordert.Da das NondatabaseConvertAlecriterion das, was sein Name vermuten lässt, muss dies als Aufzählung durchgeführt werden.Berücksichtigen Sie jedoch:

generasacodicetagpre.

In diesem Fall wird, wenn res aufgelistet, abgefragt oder anderweitig verwendet wird, so viel Arbeit wie möglich an die Datenbank übergeben wird, die ausreichend ist, um den Job fortzusetzen.Angenommen, es ist in der Tat wirklich unmöglich, umzuschreiben, damit alle Arbeiten an die Datenbank gesendet werden können, dies kann ein geeigneter Kompromiss sein.

Es gibt drei Implementierungen von AsEnumerable.

DataTableExtensions.AsEnumerable

Verlängert ein DataTable um es zu geben IEnumerable Schnittstelle, damit Sie Linq gegen die verwenden können DataTable.

Enumerable.AsEnumerable<TSource> Und ParallelEnumerable.AsEnumerable<TSource>

Der AsEnumerable<TSource>(IEnumerable<TSource>) Die Methode hat keinen anderen Effekt, als die Kompilierungszeit-Quelle von einem Typ zu ändern, der implementiert IEnumerable<T> Zu IEnumerable<T> selbst.

AsEnumerable<TSource>(IEnumerable<TSource>) kann verwendet werden, um zwischen Abfrage -Implementierungen zu wählen, wenn eine Sequenz implementiert IEnumerable<T> hat aber auch eine andere Reihe von öffentlichen Anfragethoden zur Verfügung.Zum Beispiel eine generische Klasse gegeben Table das umsetzt IEnumerable<T> und verfügt über eigene Methoden wie z Where, Select, Und SelectMany, ein Anruf an Where würde die Öffentlichkeit anrufen Where Methode von Table.A Table Typ, der eine Datenbanktabelle darstellt, könnte einen haben Where Methode, die das Prädikat -Argument als Expressionsbaum nimmt und den Baum für die Remoteausführung in SQL umwandelt.Wenn die Remoteausführung nicht erwünscht ist, zum Beispiel, weil das Prädikat eine lokale Methode aufruft, die AsEnumerable<TSource> Methode kann verwendet werden, um die benutzerdefinierten Methoden auszublenden und stattdessen die Standard -Abfrageberatoren zur Verfügung zu stellen.

Mit anderen Worten.

Wenn ich eine habe

IQueryable<X> sequence = ...;

von einem LinqProvider wie Entity Framework, und das tue ich,

sequence.Where(x => SomeUnusualPredicate(x));

Diese Abfrage wird erstellt und auf dem Server ausgeführt.Dies schlägt zur Laufzeit fehl, da das EntityFramework nicht weiß, wie es konvertieren soll SomeUnusualPredicate in SQL.

Wenn ich möchte, dass die Anweisung stattdessen mit Linq to Objects ausgeführt wird, tue ich Folgendes:

sequence.AsEnumerable().Where(x => SomeUnusualPredicate(x));

Jetzt gibt der Server alle Daten zurück und die Enumerable.Where from Linq to Objects wird anstelle der Implementierung des Abfrageanbieters verwendet.

Es spielt keine Rolle, dass Entity Framework nicht weiß, wie es interpretieren soll SomeUnusualPredicate, meine Funktion wird direkt verwendet.(Dies kann jedoch ein ineffizienter Ansatz sein, da alle Zeilen vom Server zurückgegeben werden.)

Ich glaube, der Aseumumerable sagt dem Compiler einfach mit, welche Erweiterungsmethoden (in diesem Fall diejenigen, die für IENumerierbar definiert sind, anstelle derjenigen für yleryable). Die Ausführung der Abfrage ist immer noch aufgeschoben, bis Sie Toarray anrufen oder darauf aufzählen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top