2011-02-15 40 views
4

我实现了一个通用的存储库实体框架4.下面是一个简单化的版本,其中AllAppContainer是EF4对象上下文:实体框架,通用Repository模式和奇怪的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; 
    } 
} 

的一个方法是QueryCount(),我想作为选择Count(*)...其中行的SQL(不返回实际记录)。

直向前方?你会觉得......首先,让我们做同样的事情在非存储库版本,执行对项目实体的计数:

AllAppContainer allAppContainer = new AllAppContainer(); 
int nonRepCount = allAppContainer.Items.Count(item => item.Id > 0); 

SQL Server事件探查说生成的SQL是:

SELECT 
[GroupBy1].[A1] AS [C1] 
FROM (SELECT 
    COUNT(1) AS [A1] 
    FROM [dbo].[Items] AS [Extent1] 
    WHERE [Extent1].[Id] > 0 
) AS [GroupBy1] 

呜呼!得分了!

现在让我们用我的仓库QueryCount调用相同:

Repository<Item> repository = new Repository<Item>(); 
int repCount = repository.QueryCount(item => item.Id > 0); 

这里生成的SQL:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[SmallField] AS [SmallField] 
FROM [dbo].[Items] AS [Extent1] 

没错,EF还是返回了全套资料,然后调用COUNT()内存中有

为了好玩,我试图改变到相关的行库QueryCount:

int queryCount = new AllAppContainer().CreateObjectSet<T>().Count(predicate); 

和非存储库线:

int nonRepCount = allAppContainer1.CreateObjectSet<Item>().Count(item => item.Id > 0); 

但对于每个生成的SQL是和以前一样。

现在为什么所有这个存储库返回所有匹配记录然后计数发生时,它不适用于非存储库?有没有办法做我想通过我的通用资源库,即数据库。我无法对内存计数性能造成影响。

回答

7

你需要使用Expression<Func<TSource, bool>> predicateCount否则框架使用后者从DB整个集合能够调用每个项目的Enumerable.Count<TSource> Method (IEnumerable<TSource>, Func<TSource, Boolean>),所以你的方法应该是:

public int QueryCount(Expression<Func<T, Boolean>> predicate) 
{ 
    int queryCount = entitySet.Count(predicate); 
    return queryCount; 
} 
+1

+1见http://stackoverflow.com/questions/4855399和http://stackoverflow.com/questions/2675536 - 我几乎会称这是一个错误。 – 2011-02-15 18:41:34