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:
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:
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?
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.
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.
.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%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.
Any()
, das auf diese Weise verwendet wird, wird zurückgestellt.
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).
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.
Tags und Links c# linq deferred-execution iqueryable