Je suis confus quant à la différence. Étant assez nouveau sur .Net, je sais que je peux interroger IEnumerables
à l’aide des extensions Linq. Alors, quelle est cette IQueryable
et en quoi diffère-t-elle?
Voir aussi Quelle est la différence entre IQueryable [T] et IEnumerable [T]? qui chevauche cette question.
IEnumerable<T>
représente un curseur avant uniquement de T
. Les méthodes d’extension .NET 3.5 ajoutées qui incluaient le LINQ standard query operators
comme Where
et First
, avec tous les opérateurs nécessitant des prédicats ou des fonctions anonymes prenant Func<T>
.
IQueryable<T>
implémente les mêmes opérateurs de requête standard LINQ, mais accepte Expression<Func<T>>
pour les fonctions prédites et anonymes. Expression<T>
est une arborescence d'expression compilée, une version fragmentée de la méthode ("semi-compilée" si vous voulez) qui peut être analysée par le fournisseur de l'objet interrogeable 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é comme n'importe quelle autre méthode. Enumerable.Where
exécutera la méthode une fois pour chaque personne, yield
ing valeurs pour lesquelles la méthode a renvoyé 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 "est la propriété 'Age'> 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 IQueryable
soit é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
et FirstOrDefault
) pour faire des choix plus judicieux sur la manière d'exécuter la requête entière sur la source de données sous-jacente (comme en utilisant SELECT TOP 1
en SQL).
Voir:
Dans la vie réelle, si vous utilisez un ORM tel que LINQ-to-SQL
IQueryable
, la requête peut être convertie en SQL et exécutée sur le serveur de base de données.IEnumerable
, toutes les lignes seront alors extraites en mémoire en tant qu'objets avant l'exécution de la requête.Dans les deux cas, si vous n'appelez pas ToList()
ou ToArray()
, la requête sera exécutée chaque fois qu'elle sera utilisée. Par conséquent, vous avez un IQueryable
et vous remplissez 4 listes de sélection, la requête sera alors exécutée 4 fois sur 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 IEnumerable
beaucoup plus de rôles seront retirés de la base de données, puis le x.name = "a"
vérification sera effectuée par .NET.
"La principale différence est que les méthodes d'extension définies pour IQueryable prennent des objets Expression plutôt que des objets Func, ce qui signifie que le délégué reçu est une arborescence d'expression plutôt qu'une méthode à appeler. IEnumerable est idéal pour travailler avec des collections en mémoire, mais IQueryable le permet. pour une source de données distante, telle qu'une base de données ou un service Web "
Source: ici
IEnumerable IEnumerable convient le mieux pour travailler avec une collection en mémoire. IEnumerable ne se déplace pas d’un élément à l’autre, il s’agit d’une collecte en avant uniquement.
IQueryable IQueryable convient le mieux à une source de données distante, telle qu'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 des requêtes basées sur la pagination et la composition).
Ainsi, lorsque vous devez simplement parcourir la collection en mémoire, utilisez IEnumerable, si vous devez manipuler la collection, comme Dataset et d'autres sources de données, utilisez IQueryable.
La principale différence est qu'IEnumerable énumérera tous ses éléments tout le temps, alors qu'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/peu importe afin de générer des résultats.
Avoir une expression de requête donne 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 sinon impossibles. Au lieu de renvoyer tous les éléments puis d'en jeter la plupart à cause 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é. Les expressions étant des structures de données pouvant être explorées, vous pouvez effectuer des opérations telles que la sérialisation de la requête et son envoi vers une machine distante (par exemple, linq-to-sql).
Premièrement, IEnumerable se trouve dans un espace de noms System.Collections, tandis que IQueryable se trouve dans un espace de noms System.Linq. Si vous utilisez IEnumerable lorsque vous interrogez des données à partir de collections en mémoire, telles que List, Array etc, ainsi que lorsque vous interrogez des données à partir de collections en mémoire externe (telles que base de données distante, service), vous utilisez donc IQueryable. En interrogeant les 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 du 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, moins de travail et devient rapide.
IQueriable est identique à IEnumerable, mais il fournit également des fonctionnalités supplémentaires pour implémenter des requêtes personnalisées avec Linq. Voici la description sur MSDN: http://msdn.Microsoft.com/en-us/library/system.linq.iqueryable.aspx