Was ist der Unterschied zwischen IQueryable und IEnumerable?

Antworten:

186

IEnumerable<T>repräsentiert einen Nur-Vorwärts-Cursor von T. .NET 3.5 fügte Erweiterungsmethoden hinzu, die LINQ standard query operatorsähnliche Whereund enthalten First, wobei alle Operatoren, für die Prädikate oder anonyme Funktionen erforderlich sind, verwendet werden Func<T>.

IQueryable<T>implementiert dieselben LINQ-Standardabfrageoperatoren, akzeptiert jedoch Expression<Func<T>>Prädikate und anonyme Funktionen. Expression<T>ist ein kompilierter Ausdrucksbaum, eine aufgeschlüsselte Version der Methode ("halb kompiliert", wenn Sie so wollen), die vom Anbieter des Abfragbaren 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 x => x.Age > 18befindet sich eine anonyme Methode ( Func<Person, bool>), die wie jede andere Methode ausgeführt werden kann. Enumerable.Whereführt die Methode einmal für jede Person aus und gibt yieldWerte an, für die die Methode zurückgegeben wurde true.

Im zweiten Block x => x.Age > 18befindet sich ein Ausdrucksbaum ( Expression<Func<Person, bool>>), der als "Ist die Eigenschaft 'Alter'> 18" angesehen werden kann.

Dadurch können Dinge wie LINQ-to-SQL existieren, da sie den Ausdrucksbaum analysieren und in äquivalentes SQL konvertieren können. Und da der Anbieter erst ausführen muss, wenn der IQueryableaufgezählt ist (schließlich implementiert er IEnumerable<T>), kann er mehrere Abfrageoperatoren (im obigen Beispiel Whereund FirstOrDefault) kombinieren , um intelligentere Entscheidungen darüber zu treffen, wie die gesamte Abfrage für die zugrunde liegenden Daten ausgeführt werden soll Quelle (wie SELECT TOP 1in SQL).

Sehen:

Richard Szalay
quelle
1
ziemlich kurze Antwort
Ashveli
83

Im wirklichen Leben, wenn Sie ein ORM wie LINQ-to-SQL verwenden

  • Wenn Sie eine erstellen IQueryable, wird die Abfrage möglicherweise in SQL konvertiert und auf dem Datenbankserver ausgeführt
  • Wenn Sie eine erstellen IEnumerable, werden alle Zeilen als Objekte in den Speicher gezogen, bevor die Abfrage ausgeführt wird.

In beiden Fällen wird die Abfrage viermal für die Datenbank ausgeführt, wenn Sie eine Abfrage nicht aufrufen ToList()oder ToArray()dann bei jeder Verwendung ausgeführt werden. Wenn Sie beispielsweise eine Abfrage haben IQueryableund 4 Listenfelder daraus ausfüllen.

Auch wenn Sie Ihre Anfrage erweitern:

q.Select(x.name = "a").ToList()

Dann wird mit einem IQueryabledie generierte SQL enthalten where name = "a", aber mit IEnumerableviel mehr Rollen werden aus der Datenbank zurückgezogen, dann wird die x.name = "a"Prüfung von .NET durchgeführt.

Ian Ringrose
quelle
"Abfrage kann in SQL konvertiert werden": Ich habe das "Kann sein" nicht erhalten. Wenn ich eine IEnumerable habe und eine 'komplexe Kette' erstelle, wird diese (offensichtlich) im Gegensatz zu IQueryable nicht in eine 'optimierte' SQL-Abfrage übersetzt. Ich möchte nur bestätigen, was es bedeutet, wenn Sie sagen, dass alle Zeilen in den Speicher gezogen werden. Nehmen wir an, ich habe zwei where-Klauseln. Werden dann alle Tupel der Entitäten zuerst in den Speicher abgerufen und dann wird die normale "In-Memory" -Filterung durchgeführt?
Vaibhav
36

"Der Hauptunterschied besteht darin, dass die für IQueryable definierten Erweiterungsmethoden Ausdrucksobjekte anstelle von Func-Objekten verwenden. Dies bedeutet, dass der empfangene Delegat ein Ausdrucksbaum anstelle einer aufzurufenden Methode ist. IEnumerable eignet sich hervorragend für die Arbeit mit speicherinternen Sammlungen, IQueryable jedoch für eine entfernte Datenquelle wie eine Datenbank oder einen Webdienst "

Quelle: hier

Gabe
quelle
19

IEnumerable IEnumerable eignet sich am besten für die Arbeit mit der In-Memory-Sammlung. IEnumerable bewegt sich nicht zwischen Elementen, sondern ist nur eine Vorwärtssammlung.

IQueryable IQueryable eignet sich am besten für entfernte Datenquellen wie Datenbanken oder Webdienste. IQueryable ist eine sehr leistungsstarke Funktion, die eine Vielzahl interessanter Szenarien für die verzögerte Ausführung ermöglicht (z. B. Paging- und kompositionsbasierte Abfragen).

Wenn Sie also einfach die In-Memory-Sammlung durchlaufen müssen, verwenden Sie IEnumerable. Wenn Sie die Sammlung wie Dataset und andere Datenquellen bearbeiten möchten, verwenden Sie IQueryable

Talha
quelle
10

Der Hauptunterschied besteht darin, dass IEnumerable ständig alle seine Elemente auflistet, während IQueryable Elemente auflistet oder sogar andere Dinge basierend auf einer Abfrage ausführt. Die Abfrage ist ein Ausdruck (eine Datendarstellung von .NET-Code), den ein IQueryProvider untersuchen / 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 anwenden. Anstatt alle Elemente zurückzugeben und dann die meisten aufgrund einer 'Where'-Klausel wegzuwerfen, könnte der Anbieter eine Hash-Tabelle verwenden, um Elemente mit einem bestimmten Schlüssel zu finden.

Der zweite Vorteil ist die Flexibilität. Da Ausdrücke explorierbare Datenstrukturen sind, können Sie beispielsweise die Abfrage serialisieren und an einen Remotecomputer (z. B. linq-to-sql) senden.

Craig Gidney
quelle
1

Erstens werden IEnumerable in einem System.Collections-Namespace gefunden, während IQueryable in einem System.Linq-Namespace gefunden werden. Wenn Sie IEnumerable verwenden, wenn Sie Daten aus In-Memory-Sammlungen wie List, Array-Sammlung usw. abfragen. Wenn Sie Daten aus Out-Memory-Sammlungen (wie Remote-Datenbank, Service) abfragen, verwenden Sie IQueryable. Während IEnumerable beim Abfragen von Daten aus der Datenbank eine Auswahlabfrage auf der Serverseite ausführt, Daten auf der Clientseite in den Speicher lädt und dann Daten filtert. Daher macht mehr Arbeit und wird langsam. Beim Abfragen von Daten aus der Datenbank führt IQueryable eine Auswahlabfrage auf der Serverseite mit allen Filtern aus. Daher macht weniger Arbeit und wird schnell.

Nayeem Mansoori
quelle