当前位置: 首页 > 面试题库 >

实体框架,通用存储库模式和奇怪的SQL生成

艾哲
2023-03-14
问题内容

我已经为Entity Framework 4实现了通用存储库。这是一个简化版本,其中AllAppContainer是EF4对象上下文:

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(),我想将其用作 select Count(*)… SQL行(不返回实际记录)。

直截了当?您可能会想…首先,让我们做同一件事的非存储库版本,对Item实体进行计数:

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

SQL Server Profiler说生成的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()

为了好玩,我尝试将Repository QueryCount中的相关行更改为:

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

和非存储库行到:

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

但是每个生成的SQL与以前相同。

现在为什么为什么所有非非存储库都返回所有匹配记录然后计数的存储库呢?并且有什么方法可以通过我的通用存储库来执行我想要的操作,即在db处计数。我无法接受内存计数性能方面的问题。


问题答案:

您需要使用Expression<Func<TSource, bool>>predicate自己Count的框架,否则框架将使用框架,Enumerable.Count<TSource> Method(IEnumerable<TSource>, Func<TSource, Boolean>)该框架从DB获取整个集合以能够调用每个项目,因此您的方法应为:

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


 类似资料:
  • 有几个很好的博客关于如何使用泛型类实现存储库模式和工作单元模式。 使用实体框架6.1实现数据访问层 实现存储库和工作单元模式 这个想法是,定义一个通用接口IRepository和一个隐藏数据实际访问方式的类存储库。可以使用实体框架DbContext来访问它,或者存储库可能是用于单元测试的内存集合。 我经常看到添加了几个与Queryable和/或Enumerable函数类似的Query函数。 例如,

  • 在我的场景中,我在运行时在“com.mrg.domain”包下生成hibernate实体类。在我的通用restcontroller中,我可以根据@PathVariable创建这些实体的实例。以下代码适用于此。。 现在,我试图实现的下一步是一个通用的jpa存储库(如下所示),这样我就可以持久化运行时生成的模型,而无需为每个实体实现存储库。但是还没有找到解决方案。 下面的主题和许多其他主题实现了通用存

  • 我正在开发一个应用程序,用户可以看到一组缩小的图像,然后按“确定”下载所有的原始文件,将它们放入压缩文件并发送压缩文件。 该应用程序使用聚合物,聚合火,火力(包括存储)。 在上传图像期间,我将原始文件和缩小后的文件的下载网址和存储参考都保存在数据库中。 当我将下载url放在iron image元素中以在浏览器中显示图像时,一切都很正常,缩小的图像显示在屏幕上。当我试图通过XMLHttpReques

  • 我在向数据库添加一个包含与现有对象关系的实体时遇到了麻烦。我搜索了很多,但找不到合适的解决方案。我会尽可能简单地描述这个。 在存储库中,我添加了这样的记录。这是泛型类 现在当我尝试添加这样的新记录时 商店关系被添加为新商店,并获得新ID。有人知道我如何解决这个问题吗? 数据库示例: 这是我关于stackoverflow的第一个问题。

  • 问题内容: 我在SQL Server中创建了用户定义的表类型: 我正在使用存储过程将记录插入数据库中: 而且我想使用EF执行此存储过程,但这是问题所在:如何将用户定义的表传递给存储过程? 我尝试将存储过程添加到模型中,但是无法在更新的上下文中找到所需的存储过程。 我要执行的操作是对表执行批量插入,这是我当前正在使用的方法: 当前,我使用循环在列表中循环以将项目插入DB,但是如果列表中有很多项目,则