Was nützt es IQueryable
im Kontext von LINQ?
Wird es zur Entwicklung von Erweiterungsmethoden oder für andere Zwecke verwendet?
quelle
Was nützt es IQueryable
im Kontext von LINQ?
Wird es zur Entwicklung von Erweiterungsmethoden oder für andere Zwecke verwendet?
Die Antwort von Marc Gravell ist sehr vollständig, aber ich dachte, ich würde auch aus Sicht des Benutzers etwas dazu hinzufügen ...
Der Hauptunterschied aus der Sicht eines Benutzers besteht darin, dass, wenn Sie verwenden IQueryable<T>
(mit einem Anbieter, der die Dinge richtig unterstützt) viele Ressourcen sparen können.
Wenn Sie beispielsweise mit vielen ORM-Systemen gegen eine entfernte Datenbank arbeiten, haben Sie die Möglichkeit, Daten auf zwei Arten aus einer Tabelle abzurufen: eine, die eine zurückgibt IEnumerable<T>
, und eine, die eine zurückgibt IQueryable<T>
. Angenommen, Sie haben eine Produkttabelle und möchten alle Produkte erhalten, deren Kosten> 25 USD betragen.
Wenn Sie tun:
IEnumerable<Product> products = myORM.GetProducts();
var productsOver25 = products.Where(p => p.Cost >= 25.00);
Was hier passiert, ist, dass die Datenbank alle Produkte lädt und sie über die Leitung an Ihr Programm weiterleitet. Ihr Programm filtert dann die Daten. Im Wesentlichen führt die Datenbank ein SELECT * FROM Products
und gibt JEDES Produkt an Sie zurück.
Mit dem richtigen IQueryable<T>
Anbieter können Sie dagegen Folgendes tun:
IQueryable<Product> products = myORM.GetQueryableProducts();
var productsOver25 = products.Where(p => p.Cost >= 25.00);
Der Code sieht gleich aus, aber der Unterschied besteht darin, dass die ausgeführte SQL ausgeführt wird SELECT * FROM Products WHERE Cost >= 25
.
Aus Ihrer Sicht als Entwickler sieht dies genauso aus. Unter Leistungsgesichtspunkten können Sie jedoch nur 2 Datensätze über das Netzwerk zurückgeben, anstatt 20.000 ....
IQueryable<Product>
- spezifisch für Ihr ORM oder Repository usw.foreach
oder aufrufenToList()
), treffen Sie die Datenbank nicht wirklich.Im Wesentlichen ist seine Aufgabe sehr ähnlich
IEnumerable<T>
- um eine abfragbare Datenquelle darzustellen - mit dem Unterschied, dass die verschiedenen LINQ-Methoden (onQueryable
) spezifischer sein können, um die Abfrage mithilfe vonExpression
Bäumen anstatt mit Delegaten zu erstellen (was auch immer der Fall ist)Enumerable
verwendet wird).Die Ausdrucksbäume können von Ihrem ausgewählten LINQ-Anbieter überprüft und in eine tatsächliche Abfrage umgewandelt werden - obwohl dies an sich schon eine schwarze Kunst ist.
Dies liegt wirklich am
ElementType
,Expression
undProvider
- aber in Wirklichkeit müssen Sie sich als Benutzer selten darum kümmern . Nur ein LINQ- Implementierer muss die wichtigsten Details kennen.Re Kommentare; Ich bin mir nicht ganz sicher, was Sie als Beispiel wollen, aber betrachten Sie LINQ-to-SQL; Das zentrale Objekt hier ist a
DataContext
, das unseren Datenbank-Wrapper darstellt. Dies hat normalerweise eine Eigenschaft pro Tabelle (zum BeispielCustomers
) und eine Tabelle implementiertIQueryable<Customer>
. Aber wir verwenden nicht so viel direkt; Erwägen:Dies wird (vom C # -Compiler):
was wiederum (vom C # -Compiler) wie folgt interpretiert wird:
Wichtig ist, dass die statischen Methoden für
Queryable
Ausdrucksbäume verwendet werden, die anstelle der regulären IL zu einem Objektmodell kompiliert werden. Wenn wir zum Beispiel nur das "Wo" betrachten, erhalten wir etwas Vergleichbares zu:Hat der Compiler nicht viel für uns getan? Dieses Objektmodell kann auseinandergerissen, auf seine Bedeutung überprüft und vom TSQL-Generator wieder zusammengesetzt werden.
(Die Zeichenfolge könnte als Parameter enden; ich kann mich nicht erinnern)
Nichts davon wäre möglich, wenn wir nur einen Delegierten eingesetzt hätten. Und dies ist der Punkt von
Queryable
/IQueryable<T>
: Es bietet den Einstiegspunkt für die Verwendung von Ausdrucksbäumen.All dies ist sehr komplex, daher ist es eine gute Aufgabe, dass der Compiler es uns schön und einfach macht.
Weitere Informationen finden Sie unter " C # in Depth " oder " LINQ in Action ". Beide enthalten Informationen zu diesen Themen.
quelle
Obwohl Reed Copsey und Marc Gravell bereits genug
IQueryable
(und auchIEnumerable
) genug beschrieben haben, möchte ich hier etwas mehr hinzufügen, indem ich ein kleines Beispiel dazu gebeIQueryable
undIEnumerable
ebenso viele Benutzer danach fragtenBeispiel : Ich habe zwei Tabellen in der Datenbank erstellt
Der Primärschlüssel (
PersonId
) der TabelleEmployee
ist auch ein Forgein-Schlüssel (personid
) der TabellePerson
Als nächstes habe ich ado.net Entity Model in meine Anwendung eingefügt und unten eine Serviceklasse erstellt
sie enthalten die gleiche linq. Es rief an
program.cs
wie unten definiertDie Ausgabe ist offensichtlich für beide gleich
Die Frage ist also, was / wo ist der Unterschied? Es scheint keinen Unterschied zu geben, oder? Ja wirklich!!
Werfen wir einen Blick auf SQL-Abfragen, die in diesem Zeitraum von Entity Framwork 5 generiert und ausgeführt wurden
IQueryable Ausführungsteil
IEnumerable Ausführungsteil
Gemeinsames Skript für beide Ausführungsteile
Sie haben jetzt einige Fragen, lassen Sie mich diese erraten und versuchen, sie zu beantworten
Warum werden unterschiedliche Skripte für dasselbe Ergebnis generiert?
Lassen Sie uns hier einige Punkte herausfinden,
Alle Abfragen haben einen gemeinsamen Teil
WHERE [Extent1].[PersonId] IN (0,1,2,3)
Warum? Weil sowohl function
IQueryable<Employee> GetEmployeeAndPersonDetailIQueryable
als auchIEnumerable<Employee> GetEmployeeAndPersonDetailIEnumerable
ofSomeServiceClass
eine gemeinsame Zeile in linq-Abfragen enthältwhere employeesToCollect.Contains(e.PersonId)
Als warum das
AND (N'M' = [Extent1].[Gender])
Teil in fehltIEnumerable
Ausführungsteil, während in Funktion wir verwendeten AufrufWhere(i => i.Gender == "M") in
program.cs`Was Entity Framwork tut, wenn eine
IQueryable
Methode aufgerufen wird, nimmt sie eine in die Methode geschriebene linq-Anweisung und versucht herauszufinden, ob mehr linq-Ausdrücke in der Ergebnismenge definiert sind. Anschließend werden alle definierten linq-Abfragen erfasst, bis das Ergebnis abgerufen werden muss, und es wird eine geeignetere SQL erstellt Abfrage auszuführen.Es bietet viele Vorteile wie:
wie hier im Beispiel SQL Server kehrte nur zwei Zeilen nach der Ausführung von IQueryable zur Anwendung zurück, wurde aber zurückgegeben drei Zeilen für IEnumerable Abfrage warum?
Im Falle von
IEnumerable
Methode hat das Entity Framework die in die Methode geschriebene linq-Anweisung verwendet und eine SQL-Abfrage erstellt, wenn das Ergebnis abgerufen werden muss. Der Rest-Linq-Teil zum Erstellen der SQL-Abfrage ist nicht enthalten. Wie hier wird im SQL Server in der Spalte keine Filterung durchgeführtgender
.Aber die Ausgänge sind gleich? Weil 'IEnumerable das Ergebnis auf Anwendungsebene weiter filtert, nachdem das Ergebnis vom SQL Server abgerufen wurde
Also, was sollte jemand wählen? Ich persönlich bevorzuge es, das Funktionsergebnis so zu definieren,
IQueryable<T>
dass es viele Vorteile bietetIEnumerable
wie Sie zwei oder mehr IQueryable Funktionen kommen könnte, die auf SQL Server spezifischere Skript zu generieren.Hier im Beispiel können Sie sehen
IQueryable Query(IQueryableQuery2)
, dass ein spezifischeres Skript generiert wird, alsIEnumerable query(IEnumerableQuery2)
es aus meiner Sicht viel akzeptabler ist.quelle
Es ermöglicht weitere Abfragen in der Folge. Wenn dies über eine Servicegrenze hinausgehen würde, könnte der Benutzer dieses IQueryable-Objekts mehr damit tun.
Wenn Sie beispielsweise das verzögerte Laden mit nhibernate verwenden, kann dies dazu führen, dass das Diagramm bei Bedarf geladen wird.
quelle