Quelle est la différence entre IQueryable<T> et IEnumerable<T> ?
Y a-t-il un avantage à utiliser AsQueryable ?
Quelle est la différence entre IQueryable<T> et IEnumerable<T> ?
Tout d'abord, IQueryable<T> étend l'interface IEnumerable<T>, donc tout ce que vous pouvez faire avec un IEnumerable<T> "ordinaire", vous pouvez également le faire avec un IQueryable<T>.
IEnumerable<T> a simplement une fonction GetEnumerator() qui renvoie un Enumérateur<T> pour lequel vous pouvez appeler son MoveNext() pour itérer à travers une séquence de T .
Ce que IQueryable<T> a que IEnumerable<T> n'a pas Il y a deux propriétés en particulier - une qui indique une fournisseur de requêtes (par exemple, un fournisseur LINQ to SQL) et un autre qui pointe vers un expression de requête représentant l'objet IQueryable<T> sous la forme d'une expression traçable à l'exécution qui peut être comprise 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 soit levée).
L'expression peut être simplement 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. Le fournisseur de requêtes IQueryProvider.Execute() ou IQueryProvider.CreateQuery() Les méthodes sont appelées avec un Expression qui lui est passé, et ensuite soit un résultat de la requête, soit un autre IQueryable est retourné, respectivement.
Le seul avantage est la commodité. AsQueryable()
transformera simplement un énumérable en un interrogeable et le renverra s'il implémente la fonction IQueryable
sinon il l'intègre dans une interface ConstantExpression
qui fait l'objet d'un retour EnumerableQuery
objet.
La principale différence est que les opérateurs LINQ pour IQueryable<T> prennent des objets Expression 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, 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 de travailler avec des éléments hors mémoire, comme une source de données distante, telle qu'une base de données ou un service Web.
Lorsque l'exécution d'une requête est effectuée "in process", tout ce qui est nécessaire est le 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 telle sorte que le fournisseur LINQ puisse la convertir dans la forme appropriée pour l'exécution hors mémoire - qu'il s'agisse d'une requête LDAP, SQL ou autre.
En savoir plus C# 3.0 et LINQ .
J'apprécie la mention des opérations hors mémoire. Elle clarifie une réelle différence pratique d'utilisation.
Au lieu de prendre des délégués comme paramètres comme le fait la méthode IEnumerable<T> Where, IQueryable<T> prendra des paramètres Expression<TDelegate>. Nous ne passons pas de code dans IQueryable<T>, nous passons des arbres d'expression (code comme données) pour que le fournisseur LINQ les analyse. C# 3.0 et LINQ
Il y a un problème avec le lien de l'image, il ne s'affiche pas dans le corps du message pour une raison quelconque. codeproject.com/KB/cs/646361/WhatHowWhere.jpg
Il s'agit d'une belle vidéo facebook qui montre comment ces interfaces diffèrent, elle vaut le coup d'œil.
https://www.facebook.com/shivprasad.koirala/posts/613989748685185
Vous trouverez ci-dessous une longue réponse descriptive à ce sujet.
Le premier point important à retenir est que l'interface "IQueryable" hérite de "IEnumerable", donc tout ce que "IEnumerable" peut faire, "IQueryable" peut aussi le faire.
Il existe de nombreuses différences, mais discutons de celle qui fait la plus grande différence. L'interface "IQueryable" est utile lorsque votre collection est chargée à l'aide de LINQ ou d'Entity framework et que vous souhaitez appliquer un filtre sur la collection.
Considérons le code simple ci-dessous qui utilise "IEnumerable" avec le framework entity. Il utilise un filtre "where" pour obtenir les enregistrements dont "EmpId" est "2".
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Le filtre est exécuté du côté client, là où se trouve le code "IEnumerable". En d'autres termes, toutes les données sont extraites de la base de données, puis le client les analyse et obtient l'enregistrement dont le numéro d'employé est "2".
Mais maintenant, dans le code ci-dessous, nous avons changé "IEnumerable" en "IQueryable". Il crée une requête SQL du côté du serveur et seules les données nécessaires sont envoyées au côté client.
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
La différence entre "IQueryable" et "IEnumerable" réside donc dans l'endroit où la logique de filtrage est exécutée. L'un s'exécute du côté client et l'autre dans la base de données.
Ainsi, si vous travaillez uniquement avec une collection de données en mémoire, "IEnumerable" est un bon choix, mais si vous voulez interroger une collection de données connectée à une base de données, "IQueryable" est un meilleur choix car il réduit le trafic réseau et utilise la puissance du langage SQL.
Bonjour, merci beaucoup pour cette merveilleuse explication. Je comprends pourquoi IQueryable est un meilleur choix pour les données "out-of-memory" mais j'ai du mal à comprendre pourquoi IEnumerable est meilleur pour les données "in-memory" ? Je pense toujours qu'il est préférable d'obtenir des données filtrées plutôt que d'obtenir des données et d'appliquer un filtre.
Quand c'est "en mémoire", cela n'a pas vraiment d'importance. les données sont déjà en mémoire, le moment exact où elles sont filtrées n'a pas d'importance.
@Imad Par exemple, la projection de données en convertissant l'entité DateTimeOffset en DateTime ne peut pas être réalisée en utilisant IQueryable ou avec EntityFunctions. La meilleure façon est d'AsEnumerable() l'objet entité, puis Select() dans un viewmodel qui contient le DateTime. Ce processus utilise des fonctions in-memory.
IEnumerable : IEnumerable est plus adapté pour travailler avec des collections en mémoire (ou des requêtes locales). IEnumerable ne se déplace pas entre les éléments, il s'agit uniquement d'une collection en avant.
IQueryable : IQueryable convient mieux aux sources de données distantes, 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 intéressants d'exécution différée (comme la pagination et les requêtes basées sur la composition).
Ainsi, lorsque vous devez simplement itérer dans la collection en mémoire, utilisez IEnumerable. Si vous devez effectuer des manipulations avec la collection, comme un ensemble de données ou d'autres sources de données, utilisez IQueryable.
L'exécution différée est disponible à la fois dans IEnumerable et IQueryable. Vous trouverez d'autres informations intéressantes ici : stackoverflow.com/questions/2876616/
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.