Was ist der Unterschied zwischen IQueryable<T>
undIEnumerable<T>
?
Siehe auch Was ist der Unterschied zwischen IQueryable und IEnumerable , der sich mit dieser Frage überschneidet ?
Was ist der Unterschied zwischen IQueryable<T>
undIEnumerable<T>
?
Siehe auch Was ist der Unterschied zwischen IQueryable und IEnumerable , der sich mit dieser Frage überschneidet ?
Antworten:
Zunächst einmal erweitert die Schnittstelle, so alles , was Sie tun können , mit einem „plain“ , können Sie auch mit einem tun .IQueryable<T>
IEnumerable<T>
IEnumerable<T>
IQueryable<T>
IEnumerable<T>
hat nur eine GetEnumerator()
Methode, die eine zurückgibt, Enumerator<T>
für die Sie ihre MoveNext()
Methode aufrufen können , um eine Folge von T zu durchlaufen .
Was dies nichtIQueryable<T>
hat, sind insbesondere zwei Eigenschaften - eine, die auf einen Abfrageanbieter verweist (z. B. einen LINQ to SQL-Anbieter), und eine andere, die auf einen Abfrageausdruck verweist, der das Objekt als einen zur Laufzeit durchlaufbaren abstrakten Syntaxbaum darstellt, der sein kann vom angegebenen Abfrageanbieter verstanden (zum größten Teil können Sie einem LINQ to Entities-Anbieter keinen LINQ to SQL-Ausdruck geben, ohne dass eine Ausnahme ausgelöst wird).IEnumerable<T>
IQueryable<T>
Der Ausdruck kann einfach ein konstanter Ausdruck des Objekts selbst oder ein komplexerer Baum einer zusammengesetzten Menge von Abfrageoperatoren und Operanden sein. Die IQueryProvider.Execute()
oder IQueryProvider.CreateQuery()
Methoden des Abfrageanbieters werden mit einem an ihn übergebenen Ausdruck aufgerufen , und dann wird entweder ein Abfrageergebnis oder ein anderes IQueryable
zurückgegeben.
AsQueryable()
wandelt nur eine Aufzählung in eine abfragbare um und gibt sie zurück, wenn sie die IQueryable
Schnittstelle implementiert , andernfalls wird sie in eine eingeschlossen ConstantExpression
, auf die in einem zurückgegebenen EnumerableQuery
Objekt verwiesen wird.
Der Hauptunterschied besteht darin, dass die LINQ-Operatoren für IQueryable<T>
Take- Expression
Objekte anstelle von Delegaten, dh die empfangene benutzerdefinierte Abfragelogik, z. B. ein Prädikat oder ein Werteselektor, in Form eines Ausdrucksbaums anstelle eines Delegaten an eine Methode vorliegen.
IEnumerable<T>
eignet sich hervorragend für die Arbeit mit Sequenzen, die im Speicher iteriert werden, aber IQueryable<T>
Ermöglicht nicht genügend Arbeitsspeicher wie eine entfernte Datenquelle wie eine Datenbank oder einen Webdienst.Wenn die Ausführung einer Abfrage "in Bearbeitung" durchgeführt werden soll , ist normalerweise nur der Code (als Code) erforderlich, um jeden Teil der Abfrage auszuführen.
Wenn die Ausführung außerhalb des Prozesses ausgeführt wird , muss die Logik der Abfrage in Daten dargestellt werden, damit der LINQ-Anbieter sie in die entsprechende Form für die Ausführung außerhalb des Speichers konvertieren kann - unabhängig davon, ob es sich um eine LDAP-Abfrage handelt. SQL oder was auch immer.
Mehr in:
Dies ist ein schönes Video auf Youtube das zeigt, wie sich diese Schnittstellen unterscheiden, eine Uhr wert.
Nachfolgend finden Sie eine lange beschreibende Antwort darauf.
Der erste wichtige Punkt, an den Sie sich erinnern sollten, ist, dass die IQueryable
Schnittstelle von erbt. IEnumerable
Was also alles IEnumerable
kann, IQueryable
kann auch.
Es gibt viele Unterschiede, aber lassen Sie uns über den einen großen Unterschied diskutieren, der den größten Unterschied macht. IEnumerable
Die Benutzeroberfläche ist nützlich, wenn Ihre Sammlung mit LINQ
oder Entity Framework geladen wird und Sie einen Filter auf die Sammlung anwenden möchten.
Betrachten Sie den folgenden einfachen Code, der IEnumerable
mit dem Entity Framework verwendet wird. Es wird ein Where
Filter verwendet, um Datensätze abzurufen, deren EmpId
ist 2
.
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Hier wird der Filter auf der Clientseite ausgeführt, auf der sich der IEnumerable
Code befindet. Mit anderen Worten, alle Daten werden aus der Datenbank abgerufen und dann auf dem Client gescannt und der Datensatz mit EmpId
is abgerufen 2
.
Aber sehen Sie jetzt den Code unten haben wir geändert IEnumerable
zu IQueryable
. Es wird eine SQL-Abfrage auf der Serverseite erstellt und nur die erforderlichen Daten werden an die Clientseite gesendet.
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Also der Unterschied zwischen IQueryable
undIEnumerable
besteht also darin, wo die Filterlogik ausgeführt wird. Einer wird auf der Clientseite und der andere auf der Datenbank ausgeführt.
Wenn Sie also nur mit speicherinterner Datenerfassung arbeiten, IEnumerable
ist dies eine gute Wahl, wenn Sie jedoch eine Datenerfassung abfragen möchten, die mit der Datenbank verbunden ist. IQueryable ist eine bessere Wahl, da es den Netzwerkverkehr reduziert und die Leistung der SQL-Sprache nutzt.
IEnumerable: IEnumerable eignet sich am besten für die Arbeit mit In-Memory-Sammlungen (oder lokalen Abfragen). IEnumerable bewegt sich nicht zwischen Elementen, sondern ist nur eine Vorwärtssammlung.
IQueryable: IQueryable eignet sich am besten für Remote-Datenquellen wie Datenbanken oder Webdienste (oder Remote-Abfragen). 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
Mit einfachen Worten, ein weiterer wesentlicher Unterschied besteht darin, dass IEnumerable eine Auswahlabfrage auf der Serverseite ausführt, Daten auf der Clientseite in den Speicher lädt und dann Daten filtert, während IQueryable eine Auswahlabfrage auf der Serverseite mit allen Filtern ausführt.
Im wirklichen Leben, wenn Sie ein ORM wie LINQ-to-SQL verwenden
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 IQueryable<T>
und 4 Listenfelder daraus ausfüllen.
Auch wenn Sie Ihre Anfrage erweitern:
q.Where(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, und die Prüfung x.name =" a "wird von .NET durchgeführt.
Der unten erwähnte kleine Test kann Ihnen helfen, einen Aspekt des Unterschieds zwischen IQueryable<T>
und zu verstehen IEnumerable<T>
. Ich habe diese Antwort aus diesem Beitrag reproduziert, in dem ich versucht habe, Korrekturen zum Beitrag eines anderen hinzuzufügen
Ich habe folgende Struktur in DB (DDL-Skript) erstellt:
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
Hier ist das Skript zum Einfügen von Datensätzen (DML-Skript):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
Mein Ziel war es nun einfach, die Top 2 Datensätze aus der Employee
Tabelle in der Datenbank zu erhalten. Ich habe meiner Konsolenanwendung ein ADO.NET-Entitätsdatenmodellelement hinzugefügt, das auf eine Employee
Tabelle in meiner Datenbank verweist, und mit dem Schreiben von LINQ-Abfragen begonnen.
Code für IQueryable Route :
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Als ich dieses Programm ausführte, hatte ich auch eine Sitzung des SQL Query-Profilers auf meiner SQL Server-Instanz gestartet. Hier ist die Zusammenfassung der Ausführung:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
Es ist nur IQueryable
klug genug, die Top (2)
Klausel auf der Seite des Datenbankservers selbst anzuwenden, sodass nur 2 von 5 Datensätzen über das Netzwerk übertragen werden. Eine weitere In-Memory-Filterung ist auf der Client-Computerseite überhaupt nicht erforderlich.
Code für IEnumerable Route :
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Zusammenfassung der Ausführung in diesem Fall:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
Jetzt werden IEnumerable
alle 5 in der Salary
Tabelle vorhandenen Datensätze angezeigt und anschließend eine speicherinterne Filterung auf dem Client-Computer durchgeführt, um die beiden besten Datensätze zu erhalten. So wurden unnötigerweise mehr Daten (in diesem Fall 3 zusätzliche Datensätze) über das Kabel übertragen.
Folgendes habe ich in einem ähnlichen Beitrag geschrieben (zu diesem Thema). (Und nein, ich zitiere mich normalerweise nicht, aber das sind sehr gute Artikel.)
"Dieser Artikel ist hilfreich: IQueryable vs IEnumerable in LINQ-to-SQL .
In diesem Artikel heißt es: „Gemäß der MSDN-Dokumentation werden bei IQueryable getätigten Aufrufen stattdessen der interne Ausdrucksbaum erstellt. "Diese Methoden, die IQueryable (Of T) erweitern, führen keine direkte Abfrage durch. Stattdessen besteht ihre Funktionalität darin, ein Ausdrucksobjekt zu erstellen, bei dem es sich um einen Ausdrucksbaum handelt, der die kumulative Abfrage darstellt."
Ausdrucksbäume sind ein sehr wichtiges Konstrukt in C # und auf der .NET-Plattform. (Sie sind im Allgemeinen wichtig, aber C # macht sie sehr nützlich.) Um den Unterschied besser zu verstehen, empfehle ich, die Unterschiede zwischen Ausdrücken und Aussagen in der offiziellen C # 5.0-Spezifikation hier zu lesen . Für fortgeschrittene theoretische Konzepte, die in die Lambda-Rechnung verzweigen, ermöglichen Ausdrücke die Unterstützung von Methoden als erstklassige Objekte. Der Unterschied zwischen IQueryable und IEnumerable konzentriert sich auf diesen Punkt. IQueryable erstellt Ausdrucksbäume, IEnumerable jedoch nicht, zumindest nicht allgemein für diejenigen von uns, die nicht in den geheimen Labors von Microsoft arbeiten.
Hier ist ein weiterer sehr nützlicher Artikel, der die Unterschiede aus Push- / Pull-Perspektive beschreibt. (Mit "Push" vs. "Pull" beziehe ich mich auf die Richtung des Datenflusses. Reaktive Programmiertechniken für .NET und C #
Hier ist ein sehr guter Artikel, der die Unterschiede zwischen Anweisungs-Lambdas und Ausdrucks-Lambdas detailliert beschreibt und die Konzepte der Ausdrucksstress ausführlicher behandelt: Wiederholung von C # -Delegierten, Ausdrucksbäumen und Lambda-Anweisungen im Vergleich zu Lambda-Ausdrücken. . "
Wir verwenden IEnumerable
und IQueryable
bearbeiten die Daten, die aus der Datenbank abgerufen werden. IQueryable
erbt von IEnumerable
, IQueryable
enthält also alle IEnumerable
Funktionen. Der Hauptunterschied zwischen IQueryable
und IEnumerable
besteht darin, dass IQueryable
die Abfrage mit Filtern ausgeführt wird, während IEnumerable
die Abfrage zuerst ausgeführt wird und dann die Daten basierend auf den Bedingungen gefiltert werden.
Eine detailliertere Unterscheidung finden Sie unten:
IEnumerable
IEnumerable
existiert im System.Collections
NamespaceIEnumerable
Führen Sie eine Auswahlabfrage auf der Serverseite aus, laden Sie Daten auf einer Clientseite in den Speicher und filtern Sie dann die DatenIEnumerable
eignet sich zum Abfragen von Daten aus speicherinternen Sammlungen wie List, ArrayIEnumerable
ist vorteilhaft für LINQ to Object- und LINQ to XML-AbfragenIQueryable
IQueryable
existiert im System.Linq
NamespaceIQueryable
führt serverseitig eine 'Auswahlabfrage' mit allen Filtern ausIQueryable
eignet sich zum Abfragen von Daten aus Sammlungen außerhalb des Speichers (z. B. Remote-Datenbank, Dienst)IQueryable
ist vorteilhaft für LINQ to SQL-AbfragenWird IEnumerable
also im Allgemeinen für den Umgang mit In-Memory-Sammlungen verwendet, während IQueryable
es im Allgemeinen zum Bearbeiten von Sammlungen verwendet wird.
Sowohl IEnumerable als auch IQueryable werden verwendet, um die Erfassung von Daten zu speichern und Datenmanipulationsvorgänge durchzuführen, beispielsweise das Filtern der Datenerfassung. Hier finden Sie den besten Unterschied Vergleich mit Beispiel. http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html
IQueryable ist schneller als IEnumerable, wenn es sich um große Datenmengen aus der Datenbank handelt, da IQueryable nur die erforderlichen Daten aus der Datenbank abruft, wobei IEnumerable alle Daten unabhängig von der Notwendigkeit aus der Datenbank abruft
ienumerable: Wenn wir uns mit Inprocess-Speicher befassen möchten, dh ohne Datenverbindung. iqueryable: Wann mit SQL Server, dh mit Datenverbindungs-Ilist: Operationen wie Objekt hinzufügen, Objekt löschen usw.