Quelle est la différence entre IQueryable et IEnumerable

Réponses:

186

IEnumerable<T>représente un curseur avant uniquement de T. .NET 3.5 a ajouté des méthodes d'extension qui incluaient les éléments LINQ standard query operatorssimilaires Whereet First, avec tous les opérateurs nécessitant des prédicats ou des fonctions anonymes Func<T>.

IQueryable<T>implémente les mêmes opérateurs de requête standard LINQ, mais accepte les Expression<Func<T>>prédicats et les fonctions anonymes. Expression<T>est un arbre d'expression compilé, une version fragmentée de la méthode ("à moitié compilée" si vous voulez) qui peut être analysée par le fournisseur de l'interrogation et utilisée en conséquence.

Par exemple:

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();

Dans le premier bloc, se x => x.Age > 18trouve une méthode anonyme ( Func<Person, bool>), qui peut être exécutée comme n'importe quelle autre méthode. Enumerable.Whereexécutera la méthode une fois pour chaque personne, en yieldingérant les valeurs pour lesquelles la méthode est retournée true.

Dans le deuxième bloc, se x => x.Age > 18trouve un arbre d'expression ( Expression<Func<Person, bool>>), qui peut être considéré comme "est la propriété 'Age'> 18".

Cela permet à des éléments tels que LINQ-to-SQL d'exister car ils peuvent analyser l'arborescence des expressions et la convertir en SQL équivalent. Et comme le fournisseur n'a pas besoin d'exécuter jusqu'à ce que le IQueryablesoit énuméré (il implémente IEnumerable<T>, après tout), il peut combiner plusieurs opérateurs de requête (dans l'exemple ci-dessus Whereet FirstOrDefault) pour faire des choix plus intelligents sur la façon d'exécuter la requête entière sur les données sous-jacentes source (comme l'utilisation SELECT TOP 1en SQL).

Voir:

Richard Szalay
la source
1
jolie réponse brève
ashveli
83

Dans la vraie vie, si vous utilisez un ORM comme LINQ-to-SQL

  • Si vous créez un IQueryable, 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, toutes les lignes seront tirées en mémoire en tant qu'objets avant d'exécuter la requête.

Dans les deux cas, si vous n'appelez pas une requête ToList()ou ToArray()alors la requête sera exécutée chaque fois qu'elle est utilisée, donc, disons, vous avez un IQueryableet vous remplissez 4 zones de liste à partir de celui-ci, alors la requête sera exécutée sur la base de données 4 fois.

Aussi si vous étendez votre requête:

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

Ensuite, avec un IQueryablele SQL généré contiendra where name = "a", mais avec IEnumerablebeaucoup plus de rôles seront retirés de la base de données, puis la x.name = "a"vérification sera effectuée par .NET.

Ian Ringrose
la source
"la requête peut être convertie en sql": je n'ai pas obtenu le 'peut-être'. De plus, si j'ai un IEnumerable et que je crée une «chaîne complexe» alors (évidemment) contrairement à IQueryable, il ne sera pas traduit en une requête SQL «optimisée». Je veux juste confirmer ce que cela signifie lorsque vous dites «toutes les lignes seront tirées en mémoire». Disons que j'ai deux clauses where, alors tous les tuples des entités seront-ils d'abord récupérés en mémoire et ensuite le filtrage normal «en mémoire» se produira?
Vaibhav
36

"La principale différence est que les méthodes d'extension définies pour IQueryable prennent des objets Expression au lieu des objets Func, ce qui signifie que le délégué qu'il reçoit est une arborescence d'expression au lieu d'une méthode à appeler. IEnumerable est idéal pour travailler avec des collections en mémoire, mais IQueryable permet pour une source de données distante, comme une base de données ou un service Web "

Source: ici

Gabe
la source
19

IEnumerable IEnumerable est le mieux adapté pour travailler avec la collection en mémoire. IEnumerable ne se déplace pas entre les éléments, il s'agit uniquement d'une collection.

IQueryable IQueryable convient mieux aux sources de données distantes, comme une base de données ou un service Web. IQueryable est une fonctionnalité très puissante qui permet une variété de scénarios d'exécution différée intéressants (comme la pagination et les requêtes basées sur la composition).

Ainsi, lorsque vous devez simplement parcourir la collection en mémoire, utilisez IEnumerable, si vous devez faire une manipulation avec la collection comme Dataset et d'autres sources de données, utilisez IQueryable

Talha
la source
11

La principale différence est que IEnumerable énumérera tous ses éléments tout le temps, tandis que IQueryable énumérera des éléments, ou même fera d'autres choses, en fonction d'une requête. La requête est une expression (une représentation de données de code .Net), qu'un IQueryProvider doit explorer / interpréter / compiler / quoi que ce soit afin de générer des résultats.

Avoir une expression de requête présente deux avantages.

Le premier avantage est l'optimisation. Étant donné que des modificateurs tels que «Où» sont inclus dans l'expression de requête, IQueryProvider peut appliquer des optimisations autrement impossibles. Au lieu de renvoyer tous les éléments puis de jeter la plupart d'entre eux en raison d'une clause «Where», le fournisseur pourrait utiliser une table de hachage pour localiser les éléments avec une clé donnée.

Le deuxième avantage est la flexibilité. Comme les expressions sont des structures de données explorables, vous pouvez faire des choses comme sérialiser la requête et l'envoyer à une machine distante (par exemple linq-to-sql).

Craig Gidney
la source
1

Premièrement, IEnumerable se trouve dans un espace de noms System.Collections tandis que les IQueryable se trouvent dans un espace de noms System.Linq. Si vous utilisez IEnumerable lors de l'interrogation de données à partir de collections en mémoire telles que List, Array, etc. Parce que lors de l'interrogation des données de la base de données, IEnumerable exécute une requête de sélection côté serveur, charge les données en mémoire côté client, puis filtre les données. Par conséquent fait plus de travail et devient lent. Lors de l'interrogation des données de la base de données, IQueryable exécute une requête de sélection côté serveur avec tous les filtres. Par conséquent fait moins de travail et devient rapide.

Nayeem Mansoori
la source