Wie wird die verzögerte Ausführung von LINQ beibehalten?

8

Angenommen, ich habe einen Ausdruck IQueryable<T> , mit dem ich die Definition kapseln, speichern und wiederverwenden oder später in eine größere Abfrage einbetten möchte. Zum Beispiel:

%Vor%

Jetzt glaube ich, dass ich das myQuery-Objekt einfach behalten und es so verwenden kann, wie ich es beschrieben habe. Aber einige Dinge, über die ich mir nicht sicher bin:

  1. Wie lässt sich das am besten parametrisieren? Anfangs habe ich dies in einer Methode definiert und dann% code_% als Ergebnis der Methode zurückgegeben. Auf diese Weise kann ich IQueryable<T> und blah als Methodenargumente definieren und ich schätze, dass jedes Mal ein neues bar erstellt wird. Ist dies der beste Weg, um die Logik von IQueryable<T> zu kapseln? Gibt es andere Möglichkeiten?

  2. Was passiert, wenn meine Abfrage in einen Skalar und nicht in IQueryable<T> aufgelöst wird? Was ist zum Beispiel, wenn diese Abfrage genau so aussehen soll wie angezeigt, aber IQueryable anhängen, um mich einfach zu lassen wissen, ob es irgendwelche übereinstimmenden Ergebnisse gibt? Wenn ich .Any() hinzufüge, dann ist das Ergebnis (...).Any() und wird sofort ausgeführt, oder? Gibt es eine Möglichkeit, diese bool -Operatoren ( Queryable , Any usw.) ohne sofortige Ausführung zu verwenden? Wie geht LINQ-to-SQL damit um?

Bearbeiten: In Teil 2 geht es mehr darum zu verstehen, was die Unterschiede zwischen SindleOrDefault und IQueryable<T>.Where(Expression<Func<T, bool>>) sind. Es scheint, als ob Letzteres nicht so flexibel ist, wenn größere Abfragen erstellt werden, bei denen die Ausführung verzögert werden soll. Der IQueryable<T>.Any(Expression<Func<T, bool>>) kann angehängt werden und dann können andere Konstrukte später angehängt und schließlich ausgeführt werden. Da Where() einen skalaren Wert zurückgibt, klingt es so, als würde es sofort ausgeführt, bevor der Rest der Abfrage erstellt werden kann.

    
mckamey 20.08.2009, 18:52
quelle

4 Antworten

5
  1. Wenn Sie einen DataContext verwenden, müssen Sie sehr vorsichtig sein, wenn Sie IQeryables weitergeben, denn sobald der Kontext get beseitigt ist, können Sie nicht mehr auf diesem IQueryable ausführen. Wenn Sie keinen Kontext verwenden, sind Sie vielleicht in Ordnung, aber seien Sie sich dessen bewusst.

  2. .Any () und .FirstOrDefault () sind nicht zurückgestellt. Wenn Sie sie aufrufen, bewirkt , dass ausgeführt wird. Dies kann jedoch nicht tun, was Sie denken, dass es tut. Zum Beispiel, in LINQ to SQL, wenn Sie eine .Any () auf einem IQueryable ausführen, fungiert es im Grunde wie ein IF EXISTS (SQL HERE).

Sie können IQueryable wie folgt verketten, wenn Sie möchten:

%Vor%     
Joseph 20.08.2009, 19:03
quelle
2

Eine wesentlich bessere Option als das Zwischenspeichern von IQueryable-Objekten ist das Zwischenspeichern von Ausdrucksbäumen. Alle IQueryable-Objekte haben eine Eigenschaft namens Expression (ich glaube), die den aktuellen Ausdrucksbaum für diese Abfrage darstellt.

Zu einem späteren Zeitpunkt können Sie die Abfrage neu erstellen, indem Sie queryable.Provider.CreateQuery (Ausdruck) oder direkt den Provider aufrufen (in Ihrem Fall einen Linq2Sql-Datenkontext).

Die Parametrisierung dieser Ausdrucksbäume ist jedoch etwas schwieriger, da sie ConstantExpressions verwenden, um einen Wert zu erstellen. Um diese Abfragen zu parametrisieren, müssen Sie die Abfrage jedes Mal neu erstellen, wenn Sie andere Parameter wünschen.

    
LorenVS 20.08.2009 19:16
quelle
1

Any() , das auf diese Weise verwendet wird, wird zurückgestellt.

%Vor%

Any() , das auf diese Weise verwendet wird, wird nicht zurückgestellt, sondern wird immer noch in SQL übersetzt (die gesamte Kundentabelle wird nicht in den Speicher geladen).

%Vor%

Wenn Sie eine verzögerte Any () möchten, tun Sie es so:

%Vor%

Was heißt so:

%Vor%

Der Nachteil ist, dass diese Technik keine Unterabfrage ermöglicht.

    
Amy B 20.08.2009 19:36
quelle
0

Erstellen Sie eine Teilanwendung Ihrer Abfrage in einem Ausdruck

%Vor%

und dann können Sie es verwenden, indem Sie ...

%Vor%

Die Abfrage könnte in einer Klasse gekapselt sein, wenn Sie sie portierbarer / wiederverwendbarer machen möchten.

%Vor%     
Neal 17.09.2009 03:29
quelle