【问题标题】:Entity Framework Count with a filter on field really slow - large count实体框架计数与字段过滤器真的很慢 - 大量计数
【发布时间】:2018-05-27 21:00:14
【问题描述】:

当我运行模型映射时,一家公司有很多成员,比如 405,000 名成员。

viewModel.EmployeeCount = company.MembershipUser.Count(x => x.Deleted == false);

当我运行 SQL 查询时,它需要几毫秒。在 ASP.NET MVC、EF6 C# 中,一个列表视图控制器命中最多可能需要 10 分钟。想法?

Company 是我的域模型实体,MembershipUser 是使用实体框架 6 而非 C#6 的公共虚拟虚拟 (FK)

当我在 CompanyController (MVC) 中请求公司列表时,我得到的列表中没有包含公司计数。当我对我的模型执行 viewModelMapping 以准备传递给视图时,我需要添加计数,并且无权访问上下文或数据库等。

            // Redisplay list of companies
            var viewModel = CrmViewModelMapping.CompanyListToCompanyViewModel(pagedCompanyList);

CompanyListToCompanyViewModel 将公司列表映射到我的 ViewModel 列表并在那里进行计数(MembershipUsers)。

我还尝试将 count 属性添加到公司 DomainModel 中,例如:

public int EmployeeCount
    {
        get
        {
            // return MembershipUser.Where(x => x.Deleted == false).Count();
            return MembershipUser.Count(x => x.Deleted == false);
        }
    }

但对于拥有大量员工的公司来说,这也需要很长时间。

这几乎就像我希望这是我的 SQL 查询:

Select *, (SELECT count(EmployeeID) as Count WHERE Employee.CompanyID = CompanyID) as employeeCount from Company

但一开始我只是假设我可以让 EF 延迟加载和子查询来完成这项工作。但是大量的开销正在杀死我。在小数据集上我看不出有什么真正的区别,但是一旦计数变大,我的网站就无法使用了。

【问题讨论】:

  • company 是什么?此外,尝试记录服务器上正在执行的查询。请注意,ASP.NET MVC 6 不存在,也永远不会存在。
  • 查看实际发出的 SQL。也许,因为这是一个导航属性,而不是 DbSet,所以公司的所有用户都是从服务器加载的,然后计算在您的应用程序中?尝试如果您转到 MemberUser 的 DbSet 并执行 Count(x => x.CompanyId == company.Id && x.Deleted == false) 会发生什么。
  • When I run the SQL query => EF生成的那个?
  • MembershipUser 属性的类型是什么?
  • MembershipUser 是连接域模型实体,MembershipUser 有一个 company_companyID 键

标签: c# asp.net-mvc entity-framework-6


【解决方案1】:

当您访问导航属性并使用 count 方法时,您将实现所有 MembershipUser 表并在 C# 中进行过滤。

这个命令有3个操作:C#去数据库执行查询,把查询结果转换成C#对象列表(materialize),在这个里面执行过滤器(x => x.Deleted == false)列表。

要解决这个问题,您可以在 MembershipUser DbSet 中进行过滤:

Db.MembershipUser.Count(x => x.Deleted == false && companyId == company.Id);

使用 DbSet 进行查询,过滤器将在数据库中完成,而不实现所有 405000 行。

【讨论】:

  • 这很有意义。我明白为什么这个查询会消失并做了一些工作并在 10 分钟后返回。但我不确定如何在代码中实现。当我在我的控制器 (MVC) 上并要求提供公司列表时,我会得到一个不包括公司数量的列表。当我对我的模型执行 viewModelMapping 以准备传递给视图时,我需要添加计数,并且无权访问上下文或数据库等。
  • @ransems,添加上下文或数据库不只是将命名空间包含到范围内吗?
  • 到目前为止,当我使用 IOC 容器从控制器传递数据,然后传递给不知道 db 或连接或 db 连接的 viewModelMapping 函数时,它是抽象的
  • 这几乎就像我需要我的 CompanyService(它执行 db 查询)来返回完整的公司实体,并且 SQL 查询中已经包含员工人数。
  • 也许我可以在 CompanyService (我的数据库访问服务)中遍历每个公司并“添加”一个计数,至少它只需要转到 db 25(最大页面大小)或更多分别获得计数 - 但计数将由 SQL 执行,不需要具体化连接的 405000 个实体。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
相关资源
最近更新 更多