62 votes

Pourquoi utiliser AsQueryable() au lieu de List() ?

Je me lance dans l'utilisation du modèle de référentiel pour l'accès aux données avec l'outil de gestion des données. Entity Framework y LINQ comme base de la mise en œuvre du référentiel non-test. La plupart des exemples que je vois retournent AsQueryable() lorsque l'appel renvoie N enregistrements au lieu de List<T>. Quel est l'avantage de faire cela ?

2 votes

Qu'est-ce qu'un référentiel non-test ?

104voto

Jonathan Allen Points 23540

AsQueryable crée simplement une requête, les instructions nécessaires pour obtenir une liste. Vous pouvez apporter d'autres modifications à la requête par la suite, par exemple en ajoutant de nouvelles clauses Where qui sont envoyées jusqu'au niveau de la base de données.

AsList renvoie une liste réelle avec tous les éléments en mémoire. Si vous y ajoutez une nouvelle cluse Where, vous ne bénéficiez pas du filtrage rapide qu'offre la base de données. Au lieu de cela, vous obtenez toutes les informations dans la liste, puis vous filtrez ce dont vous n'avez pas besoin dans l'application.

En fait, il s'agit d'attendre le dernier moment avant de s'engager.

8 votes

Je suis d'accord, mais n'oubliez pas qu'au-delà du "filtrage rapide", il y a aussi le coût de l'envoi de toutes ces informations sur le réseau.

2 votes

En outre, ce n'est pas la seule façon de procéder, car vous pourriez recevoir les filtres à appliquer au lieu de renvoyer quelque chose qui peut être filtré. La première est plus facile à utiliser si vous passez plus tard de l'utilisation d'une base de données à autre chose, par exemple un service Web ou autre.

16 votes

Autre point : si vous retournez un IQueryable, vous devez trouver un bon moyen de vous assurer que 1.) le contexte est ouvert jusqu'à ce que la requête soit exécutée et 2.) que le contexte sera correctement disposé. Renvoyer une liste présente l'avantage de pouvoir contrôler la durée de vie du contexte dans une méthode. Ce qui convient le mieux dépend des besoins réels.

26voto

Daniel Brückner Points 36242

Retour à IQueryable<T> a l'avantage de différer l'exécution jusqu'à ce que vous commenciez vraiment à énumérer le résultat et vous pouvez composer la requête avec d'autres requêtes tout en obtenant une exécution côté serveur.

Le problème est que vous ne pouvez pas contrôler la durée de vie du contexte de la base de données avec cette méthode - vous avez besoin d'un contexte ouvert et devez vous assurer qu'il reste ouvert jusqu'à l'exécution de la requête. Et ensuite, vous devez vous assurer que le contexte sera éliminé. Si vous renvoyez le résultat sous la forme d'un List<T> , T[] ou quelque chose de similaire, vous perdez l'exécution différée et l'exécution côté serveur des requêtes composées, mais vous gagnez le contrôle sur la durée de vie du contexte de la base de données.

Ce qui convient le mieux, bien sûr, dépend des besoins réels. C'est une autre question sans vérité unique.

11voto

Olmo Points 1928

AsQueryable est une méthode d'extension pour IEnumerable<T> qui pourrait faire deux choses :

  • Si le IEnumerable<T> met en œuvre IQueryable<T> se contente de lancer, sans rien faire.
  • Sinon, cela crée un "faux IEnumerable<T> ( EnumerableQuery<T> ) qui implémente chaque méthode en compilant les lambdas et en appelant les méthodes de l'extension Enumerable.

Donc, dans la plupart des cas, l'utilisation de AsQueryable est inutile, à moins que vous ne soyez obligé de passer un IQueryable à une méthode et que vous ayez un IEnumerable à la place, c'est un hack.

NOTE : AsQueryable est un hack, IQueryable bien sûr ne l'est pas !

3 votes

AsQueryable n'est pas inutile, car le cas d'utilisation que vous indiquez "forcé de passer comme IQueryable" est valide, il vous permet d'utiliser ce que IQueryable a à offrir, et c'est plus que IEnumerable. Je ne le considérerais pas comme un hack, et il a ses utilisations, voir par exemple ici : wcf.codeplex.com/ . Mais je suppose que ce que vous voulez dire, c'est qu'il ne peut pas être utilisé pour aller plus loin et influencer la façon dont les données énumérables sont produites (par exemple, en optimisant une requête), il ne fonctionnera qu'en plus de ce qui est/est créé.

4voto

dahlbyk Points 24897

Retour à IQueryable<T> différera l'exécution de la requête jusqu'à ce que ses résultats soient effectivement utilisés. D'ici là, vous pouvez également effectuer d'autres opérations d'interrogation de la base de données sur le fichier IQueryable<T> ; sur un List vous êtes limité à des opérations en mémoire généralement moins efficaces.

0 votes

Sa réponse a été soumise pendant que j'écrivais la mienne. :)

-1voto

Gsanto Points 1
  • IQueryable : C'est une sorte d'exécution différée - lazy loading donc votre requête est évaluée et hit à la base de données. Si nous ajoutons une clause supplémentaire, elle sera envoyée à la base de données avec la requête requise et les filtres.
  • IEnumerable : Est un chargement empressé donc les enregistrements seront chargés en premier dans l'opération en mémoire et ensuite l'opération sera effectuée.

Ainsi, en fonction du cas d'utilisation, par exemple lors de la consultation d'un grand nombre d'enregistrements, nous devrions utiliser la fonction IQueryable<T> si l'opération est courte et ne crée pas d'énorme consommation de mémoire. IEnumerable .

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