Quelle est la différence entre IQueryable et IEnumerable?
Quelle est la différence entre IQueryable<T>
et IEnumerable<T>
?
Voir aussi Quelle est la différence entre IQueryable et IEnumerable qui chevauche cette question.
12 réponses
tout D'abord, IQueryable<T>
étend l'interface IEnumerable<T>
, donc tout ce que vous pouvez faire avec un "plain" IEnumerable<T>
, vous pouvez aussi faire avec un IQueryable<T>
.
IEnumerable<T>
vient d'avoir une méthode GetEnumerator()
qui retourne une méthode Enumerator<T>
pour laquelle vous pouvez appeler sa méthode MoveNext()
pour itérer à travers une séquence de T .
Ce IQueryable<T>
a que IEnumerable<T>
n'est pas sont deux propriétés en particulier-l'une qui pointe vers un fournisseur de requête (par exemple, un LINQ à fournisseur SQL) et une autre pointant vers une syntaxe expression de requête représentant l'objet IQueryable<T>
comme un exécutable arbre abstrait qui peut être compris par le fournisseur de requête donné (pour la plupart, vous ne pouvez pas donner une expression LINQ to SQL à un fournisseur LINQ to Entities sans un exception levée).
l'expression peut simplement être une expression constante de l'objet lui-même ou un arbre plus complexe d'un ensemble composé d'opérateurs de requête et d'opérandes. Les méthodes IQueryProvider.Execute()
ou IQueryProvider.CreateQuery()
du fournisseur de requête sont appelées avec une Expression qui lui est transmise, et ensuite soit un résultat de requête soit un autre IQueryable
est retourné, respectivement.
la principale différence est que les opérateurs LINQ pour IQueryable<T>
prennent Expression
objets au lieu de délégués, ce qui signifie la logique de requête personnalisée qu'il reçoit, par exemple, un prédicat ou un sélecteur de valeur, est 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 choses hors de la mémoire comme un source de données distante, comme une base de données ou un service web.
exécution de la Requête:
-
lorsque l'exécution d'une requête doit être effectuée "en cours de traitement" , typiquement tout ce qui est requis est le code (en tant que code) pour exécuter chaque partie de la requête.
-
où l'exécution sera effectuée out-of-process , la logique de la requête doit être représentée dans les données de sorte que le fournisseur de LINQ puisse la convertir dans la forme appropriée pour l'exécution hors de la mémoire-que ce soit une requête LDAP, SQL ou autre.
plus de:
- LINQ:
IEnumerable<T>
etIQueryable<T>
- C# 3.0 et LINQ .
- " Le retour "à la 151920920" vs
IQueryable<T>
" - Réactif de Programmation .NET et C# Développeurs - Une Introduction À
IEnumerable
,IQueryable
,IObservable
, etIQbservable
il s'agit d'une belle vidéo sur ma page Facebook qui démontre comment ces interfaces diffèrent , mérite une montre.
ci-dessous va une longue réponse descriptive pour elle.
le premier point important à retenir est IQueryable
l'interface hérite de IEnumerable
, donc tout ce que IEnumerable
peut faire, IQueryable
peut aussi le faire.
Il y a beaucoup de différences, mais discutons de la grande différence qui fait la plus grande différence. IEnumerable
l'interface est utile lorsque votre collection est chargée en utilisant LINQ
ou le cadre D'entité et vous voulez appliquer un filtre sur la collection.
considérons le code simple ci-dessous qui utilise IEnumerable
avec le cadre d'entité. Il utilise un filtre Where
pour obtenir des enregistrements dont le EmpId
est 2
.
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
cette où le filtre est exécuté du côté du client où le code IEnumerable
est. En d'autres termes, toutes les données sont récupérées à partir de la base de données et puis au client ses balayages et obtient l'enregistrement avec EmpId
est 2
.
mais maintenant Voir le code ci-dessous nous avons changé IEnumerable
à IQueryable
. Il crée une requête SQL du côté du serveur et seules les données nécessaires sont envoyées du côté du 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'endroit où la logique du filtre est exécutée. On exécute côté client et l'autre s'exécute sur la base de données.
donc si vous travaillez avec seulement la collecte de données en mémoire IEnumerable
est un bon choix, mais si vous voulez pour la collecte de données d'interrogation qui est connecté avec 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 la collection en mémoire (ou des requêtes locales). IEnumerable ne se déplace pas entre les articles, il est en avant seulement collection.
IQueryable: IQueryable convient le mieux pour la source de données à distance, comme une base de données ou un service web (ou des requêtes à distance). IQueryable est une fonctionnalité très puissante qui permet une variété de scénarios intéressants d'exécution différée (comme le questions basées sur la composition).
donc quand vous devez simplement itérer à travers la collection en mémoire, utilisez IEnumerable, si vous avez besoin de faire toute manipulation avec la collection comme ensemble de données et d'autres sources de données, utilisez IQueryable
Dans des mots simples à l'autre différence majeure est que IEnumerable exécuter une requête select sur le côté serveur, la charge en mémoire des données côté client et ensuite filtrer les données tout en IQueryable exécuter une requête select sur le côté serveur avec tous les filtres.
dans la vraie vie, si vous utilisez un ORM comme LINQ-to-SQL
- si vous créez un IQueryable, alors la requête peut être convertie en sql et exécutée sur le serveur de base de données
- si vous créez un IEnumerable, alors toutes les lignes seront tirées dans la mémoire comme des objets avant d'exécuter la requête.
dans les deux cas si vous n'appelez pas un ToList()
ou ToArray()
alors la requête sera exécutée chaque fois qu'elle est utilisée, donc, dire, vous avez un IQueryable<T>
et vous remplissez 4 zones de liste, alors la requête sera exécutée sur la base de données 4 fois.
aussi si vous extendez votre requête:
q.Where(x.name = "a").ToList()
puis avec un IQueryable le SQL généré contiendra "where name = "a", mais avec un IEnumerable beaucoup plus de rôles seront retirés de la base de données, puis le X. name = " a " check will be done by .NET.
IEnumerable fait référence à une collection mais IQueryable n'est qu'une requête et elle sera générée à l'intérieur d'un arbre D'expressions.nous allons exécuter cette requête pour obtenir des données de la base de données.
ci-dessous mentionné petit test pourrait vous aider à comprendre un aspect de la différence entre IQueryable<T>
et IEnumerable<T>
. J'ai reproduit cette réponse de ce poste où j'essayais d'ajouter des corrections à quelqu'un d'autre poste
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 de l'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 but était de simplement obtenir les 2 premiers enregistrements de la table Employee
dans la base de données. J'ai ajouté un ADO.NET élément de modèle de données D'entité dans mon application de console pointant vers la table Employee
dans ma base de données et commencé à écrire des requêtes LINQ.
Code pour la route 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);
}
}
quand j'ai commencé à exécuter ce programme, j'avais aussi commencé une session de SQL Query profiler sur L'instance de mon serveur SQL et voici le résumé de exécution:
- nombre Total de requêtes envoyées: 1
- le texte de la Requête:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
c'est juste que IQueryable
est assez intelligent pour appliquer la clause Top (2)
du côté du serveur de base de données lui-même de sorte qu'il apporte seulement 2 sur 5 enregistrements sur le fil. Aucun autre filtrage en mémoire n'est requis du côté de l'ordinateur client.
Code de 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 cette affaire:
- nombre Total de requêtes envoyées: 1
- texte de requête capturé dans le profileur SQL:
SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]
maintenant la chose est IEnumerable
a apporté tous les 5 enregistrements présents dans Salary
table et a ensuite effectué un filtrage en mémoire sur l'ordinateur client pour obtenir les 2 premiers enregistrements. Donc plus de données (3 supplémentaires dossiers dans ce cas) ont été transférés sans raison valable.
Voici ce que j'ai écrit sur un poste similaire (sur ce sujet). (Et non, je n'ai pas l'habitude de citer moi-même, mais ce sont de très bons articles.)
"cet article est utile: IQueryable vs IEnumerable in LINQ-to-SQL .
citant cet article, " selon la documentation MSDN, les appels faits sur IQueryable fonctionnent en construisant l'arbre d'expression interne à la place. "Ces méthodes qui étendent IQueryable (Of T) n'effectuent aucune interrogeant directement. Au lieu de cela, leur fonctionnalité est de construire un objet D'Expression, qui est un arbre d'expression qui représente la requête cumulative. "'
les arbres D'Expression sont une construction très importante en C# et sur la plateforme .NET. (Ils sont importants en général, mais C# rend très utile.) Pour mieux comprendre la différence, je recommande la lecture sur les différences entre expressions et déclarations dans la spécification officielle C# 5.0 ici. pour les concepts théoriques avancés qui se ramifient dans le calcul lambda, les expressions permettent le soutien 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 arbres d'expression alors que IEnumerable ne le fait pas, 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 très utile article qui détaille les différences d'un point de vue push vs pull. (Par "push" vs "pull", je fais référence à la direction du flux de données. Réactif de Techniques de Programmation .NET et C#
voici un très bon article qui détaille les différences entre l'énoncé lambdas et expression lambdas et discute les concepts d'expression tress en plus grande profondeur: revisiter c # délégués, arbres d'expression, et lambda déclarations vs lambda expression. ."
à la fois IEnumerable et IQueryable sont utilisés pour effectuer la collecte d'une donnée et effectuer des opérations de manipulation de données par exemple le 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 à des quantités énormes de données à partir de la base de données parce que,IQueryable obtient uniquement les données requises à partir de la base de données où que IEnumerable obtient toutes les données, indépendamment de la nécessité de la base de données
ienumerable:lorsque l'on veut traiter d'inprocess de mémoire, j'.e sans dataconnection iqueryable: quand traiter avec sql server, I. e avec connexion de données ilist: opérations comme Ajouter un objet, supprimer un objet etc