Quelle est la différence(s) entre les deux .ToList(), .AsEnumerable(), AsQueryable()?
Je sais que certaines différences de LINQ to entities et LINQ to Objects qui le premier met en œuvre IQueryable
et la seconde met en œuvre IEnumerable
et ma question est portée à l'intérieur EF 5.
Ma question est quel est la différence technique(s) de ces 3 méthodes? Je vois que dans beaucoup de situations, tous les de travailler. Je vois aussi à l'aide de combinaisons d'entre eux comme .ToList().AsQueryable()
.
-
Que ces méthodes veux dire, exactement?
-
Est-il un problème de performance ou de quelque chose qui pourrait conduire à l'utilisation de l'un sur l'autre?
-
Pourquoi aurait-on utiliser, par exemple,
.ToList().AsQueryable()
au lieu de.AsQueryable()
?
Vous devez vous connecter pour publier un commentaire.
Il y a beaucoup à dire sur le sujet. Laissez-moi me concentrer sur
AsEnumerable
etAsQueryable
et de mentionnerToList()
le long du chemin.Que faire de ces méthodes?
AsEnumerable
etAsQueryable
fonte ou les convertir àIEnumerable
ouIQueryable
, respectivement. Je dis fonte ou convertir avec une raison à cela:Lorsque l'objet source déjà implémente l'interface cible, la source de l'objet lui-même est retourné, mais cast à l'interface cible. En d'autres termes: le type n'est pas changé, mais le type de compilation est.
Lorsque l'objet source n'implémente pas l'interface cible, l'objet source est converti dans un objet qui implémente l'interface cible. Donc, à la fois le type et le type de compilation sont modifiées.
Laissez-moi vous montrer cela avec quelques exemples. J'ai un peu de méthode qui rapporte le type de compilation et le type réel d'un objet (courtoisie Jon Skeet):
Essayons arbitraire linq-to-sql
Table<T>
, qui met en œuvreIQueryable
:Le résultat:
Vous voyez que la classe de la table elle-même est toujours retourné, mais sa représentation change.
Maintenant un objet qui implémente
IEnumerable
, pasIQueryable
:Les résultats:
Il est là.
AsQueryable()
a converti le tableau en unEnumerableQuery
, qui "représente uneIEnumerable<T>
collection comme unIQueryable<T>
source de données". (MSDN).Quoi?
AsEnumerable
est fréquemment utilisé pour passer de n'importe quelIQueryable
mise en œuvre de LINQ to objects (L2O), principalement parce que l'ancien ne prend pas en charge les fonctions qui L2O a. Pour plus de détails, voir Quel est l'effet de AsEnumerable() sur un LINQ Entité?.Par exemple, dans une Entité Cadre de la requête que nous ne pouvons utiliser qu'un nombre restreint de méthodes. Donc, si, par exemple, nous avons besoin d'utiliser l'une de nos propres méthodes dans une requête nous écrivent généralement quelque chose comme
ToList
– qui convertit uneIEnumerable<T>
à unList<T>
– est souvent utilisé à cette fin. L'avantage de l'utilisation deAsEnumerable
vsToList
est queAsEnumerable
ne pas exécuter la requête.AsEnumerable
préserve l'exécution différée et ne pas construire de souvent inutile intermédiaire de la liste.D'autre part, lorsque l'exécution forcée d'une requête LINQ est souhaitée,
ToList
peut être une façon de le faire.AsQueryable
peut être utilisé pour faire une énumération collection accepter expressions LINQ consolidés. Voir ici pour plus de détails: Ai-je vraiment besoin d'utiliser AsQueryable() de la collection?.Note sur l'abus de substance!
AsEnumerable
fonctionne comme une drogue. C'est une solution rapide, mais à un coût et il n'adresse pas le problème sous-jacent.Dans de nombreux Débordement de Pile réponses, je vois des gens l'application de
AsEnumerable
à réparer à peu près n'importe quel problème avec des méthodes non pris en charge dans les expressions LINQ. Mais le prix n'est pas toujours claire. Par exemple, si vous faites cela:...tout est soigneusement traduits dans une instruction SQL qui filtres (
Where
) et projets (Select
). C'est à la fois la longueur et la largeur, respectivement, de la SQL de résultat est réduite.Maintenant, supposons que les utilisateurs ne veulent voir la partie date de
CreateDate
. Dans le Cadre de l'Entité, vous allez rapidement découvrir que......n'est pas pris en charge (au moment de la rédaction). Ah, heureusement il y a le
AsEnumerable
correctif:Sûr, il court, probablement. Mais il tire l'ensemble de la table en mémoire, puis il applique le filtre et les projections. Eh bien, la plupart des gens sont assez intelligents pour faire la
Where
première:Mais encore toutes les colonnes sont extraites de la première et de la projection est effectuée dans la mémoire.
La vraie solution est:
(Mais qui nécessite juste un peu plus de connaissances...)
Que faire de ces méthodes ne PAS faire?
Maintenant une importante mise en garde. Lorsque vous ne
vous allez vous retrouver avec la source de l'objet représenté comme
IQueryable
. (Parce que les deux méthodes de fonte et de ne pas convertir).Mais quand vous ne
quel sera le résultat?
La
Select
produit unWhereSelectEnumerableIterator
. C'est un interne .Net classe qui implémenteIEnumerable
, pasIQueryable
. Une conversion à un autre type a eu lieu et la suiteAsQueryable
ne peut pas revenir à la source d'origine plus.La conséquence de cela est que l'utilisation de
AsQueryable
est pas un moyen de magie injecter une requête fournisseur de avec ses caractéristiques spécifiques dans une énumération. Supposons que vous neOù la condition ne sera jamais traduit en SQL.
AsEnumerable()
suivie par LINQ états définitivement coupe la connexion avec entity framework, fournisseur de requêtes.J'ai délibérément montrer cet exemple parce que j'ai vu des questions là où les gens par exemple essayer de 'injecter'
Include
capacités dans une collection en appelantAsQueryable
. Il compile et s'exécute, mais il ne fait rien parce que l'objet sous-jacent n'a pas deInclude
de mise en œuvre de plus.Implémentations Spécifiques
Jusqu'à présent, ce n'était que sur le
Interrogeable.AsQueryable
etÉnumérable.AsEnumerable
les méthodes d'extension. Mais, bien sûr, n'importe qui peut écrire les méthodes d'instance ou de l'extension des méthodes avec le même nom (et fonctions).En fait un exemple d'un
AsEnumerable
méthode d'extension estDataTableExtensions.AsEnumerable
.DataTable
ne pas mettre en œuvreIQueryable
ouIEnumerable
, de sorte que le régulière des méthodes d'extension ne s'applique pas.ToList()
AsEnumerable()
Func<TSource, bool>
AsQueryable()
Expression<Func<TSource, bool>>
AsQueryable()
fonctionne généralement beaucoup plus rapide queAsEnumerable()
qu'il génère de T-SQL à la première, qui comprend toutes vos où les conditions de travail dans votre Linq.ToList() va être tout en mémoire, puis vous allez travailler sur elle.
donc, ToList().où ( appliquer certains filtres ) est exécutée localement.
AsQueryable() exécute tout à distance, c'est à dire un filtre, il est envoyé à la base de données de l'application.
Queryable ne rien faire jusqu'à ce que tu l'exécuter. ToList, cependant exécute immédiatement.
Aussi, regardez cette réponse Pourquoi utiliser AsQueryable() au lieu de (Liste)?.
EDIT :
Aussi, dans votre cas, une fois que vous faites ToList() puis chaque opération suivante est local y compris AsQueryable(). Vous ne pouvez pas passer à distance une fois que vous commencer à exécuter localement.
Espérons que cela rend les choses un peu plus claire.
Rencontré une mauvaise performance sur le code ci-dessous.
Fixe avec
Pour un IQueryable, rester dans IQueryable lorsque cela est possible, essayez de ne pas être utilisé comme IEnumerable.