69 votes

Suis-je incompréhensible LINQ to SQL .AsEnumerable ()?

Considérer ce code:

var query = (from a in db.Table
             where a = SomeCondition
             select a.SomeNumber).AsEnumerable();

int recordCount = query.Count();
int totalSomeNumber = query.Sum();
decimal average = query.Average();

Supposons query prend un temps très long à exécuter. J'ai besoin d'obtenir le nombre d'enregistrements, le total des SomeNumbers'est retourné, et de prendre une moyenne à la fin. J'ai pensé basé sur ma lecture qu' .AsEnumerable() à l'exécution de la requête à l'aide de LINQ-to-SQL, puis utiliser LINQ-to-Objets pour l' Count, Sum, et Average. Au lieu de cela, quand je fais cela dans LINQPad, je vois la même requête est exécutée trois fois. Si je remplace .AsEnumerable() avec .ToList(), il ne s'est interrogé à la fois.

Ai-je raté quelque chose au sujet de ce qu' AsEnumerable est/ne?

87voto

Justin Niessner Points 144953

L'appel de AsEnumerable( ) ne garantit pas que les résultats seront exécutés immédiatement.

IQueryable est l'interface qui permet à LINQ to SQL d'effectuer sa magie. IQueryable implémente IEnumerable donc quand vous appelez AsEnumerable() , rien ne se passe vraiment.

Pour forcer l'exécution de la requête, vous devez appeler ToList() .

22voto

Adam Robinson Points 88472

Oui. Tout ce que AsEnumerable fera, c'est que les fonctions Count , Sum et Average soient exécutées côté client (en d'autres termes, cela ramènera l'ensemble des résultats au client, puis le client exécutera ces agrégats au lieu de créer des instructions COUNT() SUM() et AVG() dans SQL).

3voto

James Curran Points 55356

Eh bien, vous êtes sur la bonne voie. Le problème est qu'un IQueryable (ce que la déclaration est avant l'appel AsEnumerable ) est également un IEnumerable , de sorte que cet appel est, en fait, un non. Il faudra le forcer à une structure de données en mémoire spécifique (par exemple, ToList() ) pour forcer la requête.

1voto

Sergio Points 2387

Je présume que ToList forces de Linq pour extraire les enregistrements de la base de données. Lorsque vous effectuez la procédure de calculs sont effectués sur la dans les objets de la mémoire plutôt que d'associer la base de données.

Laissant le type de retour comme une Énumération signifie que les données ne sont pas récupérées jusqu'à ce qu'il est appelé par le code effectuer les calculs. Je suppose que le coup de c'est que la base de données est frappé trois fois - une pour chaque calcul et les données ne sont pas conservées en mémoire.

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