158 votes

Quelle est la différence entre IQueryable et IEnumerable ?

Je ne sais pas quelle est la différence. Étant donné que je suis assez novice en .Net, je sais que je peux interroger IEnumerables en utilisant les extensions Linq. Alors, qu'est-ce que c'est ? IQueryable et en quoi diffère-t-elle ?


Voir aussi Quelle est la différence entre IQueryable[T] et IEnumerable[T] ? qui recoupe cette question.

196voto

Richard Szalay Points 42486

IEnumerable<T> représente un curseur à l'avance de T . .NET 3.5 a ajouté des méthodes d'extension incluant l'élément LINQ standard query operators comme Where y First avec tous les opérateurs qui nécessitent des prédicats ou des fonctions anonymes. Func<T> .

IQueryable<T> met en œuvre les mêmes opérateurs de requête standard LINQ, mais accepte Expression<Func<T>> pour les prédicats et les fonctions anonymes. Expression<T> est un arbre d'expression compilé, une version décomposée de la méthode ("demi-compilée" si vous voulez) qui peut être analysée par le fournisseur de la table d'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, x => x.Age > 18 est une méthode anonyme ( Func<Person, bool> ), qui peut être exécutée comme toute autre méthode. Enumerable.Where exécutera la méthode une fois pour chaque personne, yield les valeurs pour lesquelles la méthode a retourné true .

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

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

Voir :

91voto

Ian Ringrose Points 19115

Dans la vie réelle, 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 la base de données.
  • Si vous créez un IEnumerable alors toutes les lignes seront mises en mémoire en tant qu'objets avant l'exécution de la requête.

Dans les deux cas, si vous n'appelez pas une fonction ToList() o ToArray() alors la requête sera exécutée à chaque fois qu'elle sera utilisée, donc, disons que vous avez une IQueryable et que vous remplissez 4 cases de liste à partir de celle-ci, la requête sera exécutée 4 fois dans la base de données.

Aussi, si vous étendez votre requête :

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

Ensuite, avec un IQueryable le SQL généré contiendra where name = "a" mais avec une IEnumerable beaucoup plus de rôles seront retirés de la base de données, alors le x.name = "a" La vérification sera effectuée par .NET.

0 votes

"la requête peut être convertie en sql" : je n'ai pas compris le "peut être". De plus, si j'ai un IEnumerable et que je crée une 'chaîne complexe', alors (évidemment) contrairement à IQueryable, elle ne sera pas convertie en une requête SQL 'optimisée'. Je veux juste confirmer ce que vous voulez dire quand vous dites que "toutes les lignes seront mises 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, puis le filtrage normal "en mémoire" se produira ?

38voto

Gabe Points 24378

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

Fuente: aquí

21voto

Talha Points 7596

IEnumerable IEnumerable est le mieux adapté pour travailler avec une collection en mémoire. IEnumerable ne se déplace pas entre les éléments, c'est une collection en avant seulement.

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 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.

11voto

Strilanc Points 7161

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

Le fait de disposer d'une expression de requête présente deux avantages.

Le premier avantage est l'optimisation. Comme des modificateurs tels que "Where" sont inclus dans l'expression de la requête, IQueryProvider peut appliquer des optimisations autrement impossibles. Au lieu de renvoyer tous les éléments puis d'en jeter la plupart en raison d'une clause "Where", le fournisseur peut utiliser une table de hachage pour localiser les éléments ayant 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).

Prograide.com

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.

Powered by:

X