j'ai mis en place un référentiel générique pour Entity Framework 4. Voici une version abêtis, où AllAppContainer est le contexte de l'objet EF4:Entity Framework, Motif de dépôt générique et étrange génération SQL
public class Repository<T> where T : class
{
protected AllAppContainer objectContext;
protected ObjectSet<T> entitySet;
public Repository()
{
objectContext = new AllAppContainer();
entitySet = objectContext.CreateObjectSet<T>();
}
public int QueryCount(Func<T, bool> predicate)
{
int queryCount = entitySet.Count(predicate);
return queryCount;
}
}
La seule méthode est QueryCount(), que je veux agir comme un sélectionnez Count (*) ... où ligne de SQL (ne pas retourner les enregistrements réels).
Droit devant? Vous penseriez ... Tout d'abord, nous allons faire une version non-dépôt de la même chose, d'effectuer un comptage sur les entités de l'article:
AllAppContainer allAppContainer = new AllAppContainer();
int nonRepCount = allAppContainer.Items.Count(item => item.Id > 0);
SQL Server Profiler dit le SQL généré est:
SELECT
[GroupBy1].[A1] AS [C1]
FROM (SELECT
COUNT(1) AS [A1]
FROM [dbo].[Items] AS [Extent1]
WHERE [Extent1].[Id] > 0
) AS [GroupBy1]
Woo-hoo! But!
Maintenant, nous allons appeler la même chose en utilisant mon référentiel QueryCount:
Repository<Item> repository = new Repository<Item>();
int repCount = repository.QueryCount(item => item.Id > 0);
Voici le SQL généré:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[SmallField] AS [SmallField]
FROM [dbo].[Items] AS [Extent1]
Oui, EF retourne l'ensemble des données, puis en appelant Count() sur elle en mémoire.
Pour le plaisir que j'ai essayé de changer la ligne correspondante dans le référentiel QueryCount à:
int queryCount = new AllAppContainer().CreateObjectSet<T>().Count(predicate);
et la ligne non-dépôt à:
int nonRepCount = allAppContainer1.CreateObjectSet<Item>().Count(item => item.Id > 0);
mais le SQL généré pour chacun d'eux est le même que précédemment .
Maintenant, pourquoi tout ce dépôt-retourne-tout-correspondance-enregistrements-puis-comptes se passe, quand ce n'est pas pour le non-dépôt? Et est-il possible de faire ce que je veux via mon dépôt générique, c'est-à-dire compter à DB. Je ne peux pas prendre le coup de performance du compte en mémoire.
+1 voir aussi http://stackoverflow.com/questions/4855399 et http://stackoverflow.com/questions/2675536 - Je dirais presque que c'est un bug. –
Wow, je ne suis pas au travail maintenant, mais je vais courir demain pour vérifier cela. Merci pour la réponse rapide K. Et merci pour les pointeurs BlueRaja - la chose frustrante était de ne pas connaître les termes à rechercher sur ce problème: le mien et les deux autres questions ont des titres/sujets complètement différents, mais apparemment proviennent de la même chose. – user603563
@BlueRaja: Que voulez-vous appeler un bug? Ne pas entièrement comprendre la différence entre IEnumerable et IQueryable n'est pas un bug. C'est une connaissance clé que vous devez avoir pour utiliser correctement Linq. –