Ich bin verwirrt über den Unterschied. Ich bin ziemlich neu in .Net und weiß, dass ich IEnumerables
mit den Linq-Erweiterungen abfragen kann. Also, was ist das IQueryable
und wie unterscheidet es sich?
Siehe auch Was ist der Unterschied zwischen IQueryable [T] und IEnumerable [T]? , der sich mit dieser Frage überschneidet.
IEnumerable<T>
repräsentiert einen Nur-Vorwärts-Cursor von T
. .NET 3.5 fügte Erweiterungsmethoden hinzu, die das LINQ standard query operators
wie Where
und First
, wobei alle Operatoren, die Prädikate oder anonyme Funktionen benötigen, Func<T>
.
IQueryable<T>
implementiert dieselben LINQ-Standardabfrageoperatoren, akzeptiert jedoch Expression<Func<T>>
für Prädikate und anonyme Funktionen. Expression<T>
ist ein kompilierter Ausdrucksbaum, eine getrennte Version der Methode ("halb kompiliert", wenn Sie so wollen), die vom Provider des abfragbaren Objekts analysiert und entsprechend verwendet werden kann.
Beispielsweise:
IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
Im ersten Block wird x => x.Age > 18
ist eine anonyme Methode (Func<Person, bool>
), die wie jede andere Methode ausgeführt werden kann. Enumerable.Where
führt die Methode einmal für jede Person aus, yield
ing Werte, für die die Methode true
zurückgegeben hat.
Im zweiten Block, x => x.Age > 18
ist ein Ausdrucksbaum (Expression<Func<Person, bool>>
), was als "ist die 'Age'-Eigenschaft> 18" angesehen werden kann.
Dies ermöglicht die Existenz von Dingen wie LINQ-to-SQL, da sie den Ausdrucksbaum analysieren und in äquivalentes SQL konvertieren können. Und weil der Provider nicht ausgeführt werden muss, bis das IQueryable
aufgezählt ist (es implementiert IEnumerable<T>
, schließlich), kann es mehrere Abfrageoperatoren (im obigen Beispiel Where
und FirstOrDefault
) kombinieren, um klügere Entscheidungen darüber zu treffen, wie die gesamte Abfrage für die zugrunde liegende Datenquelle ausgeführt werden soll (z. B. mit SELECT TOP 1
in SQL).
Sehen:
Im wirklichen Leben, wenn Sie ein ORM wie LINQ-to-SQL verwenden
IQueryable
erstellen, wird die Abfrage möglicherweise in SQL konvertiert und auf dem Datenbankserver ausgeführtIEnumerable
erstellen, werden alle Zeilen als Objekte in den Speicher abgerufen, bevor die Abfrage ausgeführt wird.Wenn Sie in beiden Fällen kein ToList()
oder ToArray()
aufrufen, wird die Abfrage bei jeder Verwendung ausgeführt, dh, Sie haben ein IQueryable
und Wenn Sie 4 Listenfelder ausfüllen, wird die Abfrage viermal für die Datenbank ausgeführt.
Auch wenn Sie Ihre Anfrage erweitern:
q.Select(x.name = "a").ToList()
Dann enthält die generierte SQL mit einem IQueryable
where name = "a"
, aber mit einem IEnumerable
werden viel mehr Rollen aus der Datenbank zurückgezogen, dann wird der x.name = "a"
wird von .NET geprüft.
"Der Hauptunterschied besteht darin, dass die für IQueryable definierten Erweiterungsmethoden Expression-Objekte anstelle von Func-Objekten verwenden, was bedeutet, dass der Delegat, den er empfängt, eine Ausdrucksbaumstruktur anstelle einer aufzurufenden Methode ist. IEnumerable eignet sich hervorragend für die Arbeit mit speicherinternen Auflistungen, IQueryable lässt dies jedoch zu für eine entfernte Datenquelle, wie eine Datenbank oder einen Webdienst "
Quelle: hier
IEnumerable IEnumerable eignet sich am besten für die Arbeit mit speicherinternen Auflistungen. IEnumerable bewegt sich nicht zwischen Elementen, sondern ist nur eine Weiterleitungssammlung.
IQueryable IQueryable eignet sich am besten für entfernte Datenquellen wie Datenbanken oder Webservices. IQueryable ist eine sehr leistungsstarke Funktion, die eine Vielzahl interessanter verzögerter Ausführungsszenarien ermöglicht (wie Abfragen auf der Basis von Paging und Kompositionen).
Wenn Sie also einfach die speicherinterne Auflistung durchlaufen müssen, verwenden Sie IEnumerable. Wenn Sie Änderungen an der Auflistung wie Dataset und anderen Datenquellen vornehmen müssen, verwenden Sie IQueryable
Der Hauptunterschied besteht darin, dass IEnumerable immer alle seine Elemente auflistet, während IQueryable auf der Grundlage einer Abfrage Elemente auflistet oder sogar andere Aktionen ausführt. Die Abfrage ist ein Ausdruck (eine Datendarstellung von .Net-Code), den ein IQueryProvider durchsuchen/interpretieren/kompilieren/was auch immer muss, um Ergebnisse zu generieren.
Ein Abfrageausdruck bietet zwei Vorteile.
Der erste Vorteil ist die Optimierung. Da Modifikatoren wie 'Where' im Abfrageausdruck enthalten sind, kann der IQueryProvider ansonsten unmögliche Optimierungen vornehmen. Anstatt alle Elemente zurückzugeben und die meisten aufgrund einer 'Where'-Klausel wegzuwerfen, könnte der Anbieter eine Hash-Tabelle verwenden, um Elemente mit einem bestimmten Schlüssel zu lokalisieren.
Der zweite Vorteil ist die Flexibilität. Da Ausdrücke explizite Datenstrukturen sind, können Sie die Abfrage beispielsweise serialisieren und an einen Remotecomputer senden (z. B. linq-to-sql).
Erstens befinden sich IEnumerable in einem System.Collections-Namespace, während sich IQueryable in einem System.Linq-Namespace befindet. Wenn Sie IEnumerable verwenden, wenn Sie Daten aus speicherinternen Sammlungen wie List, Array Collection usw. abfragen, und wenn Sie Daten aus speicherinternen Sammlungen (wie Remote-Datenbank, Dienst) abfragen, verwenden Sie IQueryable. Weil IEnumerable beim Abfragen von Daten aus der Datenbank eine Auswahlabfrage auf der Serverseite ausführt, Daten auf der Clientseite im Arbeitsspeicher lädt und dann Daten filtert. Macht also mehr Arbeit und wird langsam. Beim Abfragen von Daten aus der Datenbank führt IQueryable eine Auswahlabfrage auf der Serverseite mit allen Filtern aus. Macht also weniger Arbeit und wird schnell.
IQueriable ist dasselbe wie IEnumerable, bietet jedoch zusätzliche Funktionen zum Implementieren von benutzerdefinierten Abfragen mit Linq. Hier finden Sie eine Beschreibung zu MSDN: http://msdn.Microsoft.com/en-us/library/system.linq.iqueryable.aspx