Quelle est la difference entre IQueryable<T>
et IEnumerable<T>
?
Voir aussi Quelle est la différence entre IQueryable et IEnumerable qui chevauche cette question.
Quelle est la difference entre IQueryable<T>
et IEnumerable<T>
?
Voir aussi Quelle est la différence entre IQueryable et IEnumerable qui chevauche cette question.
Réponses:
Tout d'abord, étend l' interface, donc tout ce que vous pouvez faire avec un "simple" , vous pouvez également le faire avec un .IQueryable<T>
IEnumerable<T>
IEnumerable<T>
IQueryable<T>
IEnumerable<T>
juste a une GetEnumerator()
méthode qui retourne un Enumerator<T>
pour lequel vous pouvez appeler sa MoveNext()
méthode pour itérer à travers une séquence de T .
Ce IQueryable<T>
qui IEnumerable<T>
n'a pas ce sont deux propriétés en particulier: une qui pointe vers un fournisseur de requête (par exemple, un fournisseur LINQ to SQL) et une autre pointant vers une expression de requête représentant l' IQueryable<T>
objet comme une arborescence de syntaxe abstraite traversable par le runtime qui peut être compris par le fournisseur de requêtes donné (pour la plupart, vous ne pouvez pas donner une expression LINQ to SQL à un fournisseur LINQ to Entities sans qu'une exception ne soit levée).
L'expression peut simplement être une expression constante de l'objet lui-même ou une arborescence plus complexe d'un ensemble composé d'opérateurs et d'opérandes de requête. Le IQueryProvider.Execute()
ou les IQueryProvider.CreateQuery()
méthodes du fournisseur de requête sont appelées avec une expression qui lui est transmise, puis un résultat de requête ou un autre IQueryable
est retourné, respectivement.
AsQueryable()
va simplement transtyper un énumérable en un interrogeable et le retourner s'il implémente l' IQueryable
interface, sinon il l'enveloppe dans un ConstantExpression
, auquel il est fait référence dans un EnumerableQuery
objet renvoyé .
La principale différence est que les opérateurs LINQ pour IQueryable<T>
prendre des Expression
objets au lieu de délégués, ce qui signifie que la logique de requête personnalisée qu'il reçoit, par exemple un prédicat ou un sélecteur de valeur, se présente sous la forme d'un arbre d'expression au lieu d'un délégué à une méthode.
IEnumerable<T>
est idéal pour travailler avec des séquences qui sont itérées en mémoire, mais IQueryable<T>
permet des éléments de mémoire insuffisante comme une source de données distante, comme une base de données ou un service Web.Lorsque l'exécution d'une requête va être effectuée "en cours" , il suffit généralement du code (en tant que code) pour exécuter chaque partie de la requête.
Lorsque l'exécution sera effectuée hors processus , la logique de la requête doit être représentée dans les données de sorte que le fournisseur LINQ puisse la convertir sous la forme appropriée pour l'exécution hors mémoire - qu'il s'agisse d'une requête LDAP, SQL ou autre.
Plus dans:
Ceci est une belle vidéo sur YouTube qui montre comment ces interfaces diffèrent, vaut le détour.
Ci-dessous, une longue réponse descriptive.
Le premier point important à retenir est l' IQueryable
interface héritée de IEnumerable
, donc tout ce qui IEnumerable
peut faire IQueryable
peut aussi le faire.
Il existe de nombreuses différences, mais discutons de la grande différence qui fait la plus grande différence. IEnumerable
est utile lorsque votre collection est chargée à l'aide du LINQ
framework Entity et que vous souhaitez appliquer un filtre sur la collection.
Considérez le code simple ci-dessous qui utilise IEnumerable
avec le framework d'entité. Il utilise un Where
filtre pour obtenir les enregistrements dont il EmpId
s'agit 2
.
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
C'est là que le filtre est exécuté du côté client où se trouve le IEnumerable
code. En d'autres termes, toutes les données sont extraites de la base de données, puis sur le client, ses analyses et obtient l'enregistrement avec EmpId
est 2
.
Mais maintenant voir le code ci - dessous nous avons changé IEnumerable
pour IQueryable
. Il crée une requête SQL côté serveur et seules les données nécessaires sont envoyées côté client.
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Ainsi, la différence entre IQueryable
et IEnumerable
concerne l'emplacement d'exécution de la logique de filtrage. L'un s'exécute côté client et l'autre s'exécute sur la base de données.
Donc, si vous travaillez uniquement avec la collecte de données en mémoire IEnumerable
est un bon choix, mais si vous souhaitez interroger la collecte de données qui est connectée à la base de données `IQueryable est un meilleur choix car il réduit le trafic réseau et utilise la puissance du langage SQL.
IEnumerable: IEnumerable est le mieux adapté pour travailler avec une collection en mémoire (ou des requêtes locales). IEnumerable ne se déplace pas entre les éléments, il s'agit uniquement de la collecte vers l'avant.
IQueryable: IQueryable convient le mieux à une source de données distante, comme une base de données ou un service Web (ou des requêtes distantes). IQueryable est une fonctionnalité très puissante qui permet une variété de scénarios d'exécution différée intéressants (comme les requêtes basées sur la pagination et la composition).
Donc, lorsque vous devez simplement parcourir la collection en mémoire, utilisez IEnumerable, si vous avez besoin de manipuler la collection comme Dataset et d'autres sources de données, utilisez IQueryable
Dans la vraie vie, si vous utilisez un ORM comme LINQ-to-SQL
Dans les deux cas, si vous n'appelez pas ToList()
ou ToArray()
alors la requête sera exécutée à chaque fois qu'elle est utilisée, par exemple, vous avez un IQueryable<T>
et vous en remplissez 4 zones de liste, puis la requête sera exécutée 4 fois sur la base de données.
Aussi, si vous étendez votre requête:
q.Where(x.name = "a").ToList()
Ensuite, avec un IQueryable, le SQL généré contiendra "où nom =" a ", mais avec un IEnumerable, de nombreux autres rôles seront retirés de la base de données, puis la vérification x.name =" a "sera effectuée par .NET.
Le petit test mentionné ci-dessous pourrait vous aider à comprendre un aspect de la différence entre IQueryable<T>
et IEnumerable<T>
. J'ai reproduit cette réponse de ce post où j'essayais d'ajouter des corrections au post de quelqu'un d'autre
J'ai créé la structure suivante dans DB (script DDL):
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
Voici le script d'insertion d'enregistrement (script DML):
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
Maintenant, mon objectif était simplement d'obtenir les 2 meilleurs enregistrements de la Employee
table dans la base de données. J'ai ajouté un élément ADO.NET Entity Data Model dans mon application console pointant vers la Employee
table dans ma base de données et j'ai commencé à écrire des requêtes LINQ.
Code pour l'itinéraire IQueryable :
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);
}
}
Lorsque j'ai commencé à exécuter ce programme, j'avais également démarré une session de SQL Query profiler sur mon instance SQL Server et voici le résumé de l'exécution:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
C'est juste que IQueryable
c'est assez intelligent pour appliquer la Top (2)
clause du côté serveur de base de données lui-même, de sorte qu'il n'apporte que 2 enregistrements sur 5 sur le fil. Aucun autre filtrage en mémoire n'est nécessaire du tout côté ordinateur client.
Code pour la route IEnumerable :
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);
}
}
Résumé de l'exécution dans ce cas:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
Maintenant, la chose est IEnumerable
apportée tous les 5 enregistrements présents dans le Salary
tableau, puis effectué un filtrage en mémoire sur l'ordinateur client pour obtenir les 2 meilleurs enregistrements. Donc, plus de données (3 enregistrements supplémentaires dans ce cas) ont été transférées inutilement sur le fil.
Voici ce que j'ai écrit sur un article similaire (sur ce sujet). (Et non, je ne me cite généralement pas, mais ce sont de très bons articles.)
"Cet article est utile: IQueryable vs IEnumerable dans LINQ-to-SQL .
Citant cet article, «Conformément à la documentation MSDN, les appels effectués sur IQueryable fonctionnent en créant à la place l'arborescence des expressions internes. "Ces méthodes qui étendent IQueryable (Of T) n'effectuent aucune requête directement. Au lieu de cela, leur fonctionnalité consiste à créer un objet Expression, qui est une arborescence d'expression qui représente la requête cumulative." '
Les arbres d'expression sont une construction très importante en C # et sur la plate-forme .NET. (Ils sont importants en général, mais C # les rend très utiles.) Pour mieux comprendre la différence, je recommande de lire ici les différences entre les expressions et les instructions dans la spécification officielle C # 5.0. Pour les concepts théoriques avancés qui se ramifient en calcul lambda, les expressions permettent la prise en charge des méthodes en tant qu'objets de première classe. La différence entre IQueryable et IEnumerable est centrée autour de ce point. IQueryable construit des arborescences d'expression, contrairement à IEnumerable, du moins pas en termes généraux pour ceux d'entre nous qui ne travaillent pas dans les laboratoires secrets de Microsoft.
Voici un autre article très utile qui détaille les différences d'un point de vue push / pull. (Par «pousser» vs «tirer», je fais référence à la direction du flux de données. Techniques de programmation réactive pour .NET et C #
Voici un très bon article qui détaille les différences entre les lambdas d'instruction et les lambdas d'expression et traite plus en détail des concepts d'expression tress: Revisiter les délégués C #, les arborescences d'expression et les instructions lambda par rapport aux expressions lambda. . "
Nous utilisons IEnumerable
et IQueryable
pour manipuler les données extraites de la base de données. IQueryable
hérite de IEnumerable
, IQueryable
contient donc toutes les IEnumerable
fonctionnalités. La principale différence entre IQueryable
et IEnumerable
est que la IQueryable
requête est exécutée avec des filtres, tandis que IEnumerable
la requête est exécutée en premier, puis elle filtre les données en fonction des conditions.
Trouvez une différenciation plus détaillée ci-dessous:
IEnumerable
IEnumerable
existe dans l' System.Collections
espace de nomsIEnumerable
exécuter une requête de sélection côté serveur, charger les données en mémoire côté client, puis filtrer les donnéesIEnumerable
convient pour interroger des données à partir de collections en mémoire comme List, ArrayIEnumerable
est bénéfique pour les requêtes LINQ to Object et LINQ to XMLIQueryable
IQueryable
existe dans l' System.Linq
espace de nomsIQueryable
exécute une «requête de sélection» côté serveur avec tous les filtresIQueryable
convient pour interroger des données à partir de collections hors mémoire (comme une base de données distante, un service)IQueryable
est bénéfique pour les requêtes LINQ to SQLSo IEnumerable
est généralement utilisé pour traiter les collections en mémoire, tandis que, IQueryable
est généralement utilisé pour manipuler les collections.
IEnumerable et IQueryable sont tous deux utilisés pour conserver la collecte d'une donnée et effectuer une opération de manipulation de données, par exemple un filtrage sur la collecte de données. Ici vous pouvez trouver la meilleure comparaison de différence avec l'exemple. http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html
IQueryable est plus rapide que IEnumerable si nous avons affaire à d'énormes quantités de données de la base de données car, IQueryable obtient uniquement les données requises de la base de données où IEnumerable obtient toutes les données indépendamment de la nécessité de la base de données
ienumerable: quand nous voulons traiter la mémoire inprocess, c'est-à-dire sans connexion de données iqueryable: quand traiter avec le serveur SQL, c'est-à-dire avec la connexion de données ilist: opérations comme ajouter un objet, supprimer un objet, etc.