实体框架计数与字段上的过滤器真的很慢 - 大数

时间:2018-05-26 19:07:17

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

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

var ErrorStack = String()
Thread.callStackSymbols.forEach {
    print($0)
    ErrorStack = "\(ErrorStack)\n" + $0
}

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

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

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

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

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

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

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

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

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

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

但是早在我假设我可以让EF延迟加载和subQueries完成工作。但大量的开销正在扼杀我。在小型数据集上,我看不出真正的区别,但一旦计数变大,我的网站就无法使用。

1 个答案:

答案 0 :(得分:1)

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

此命令中有三个操作:C#转到数据库并执行查询,将查询结果转换为C#对象列表(materialize)并执行过滤器(x => x.Deleted == false)in这个清单。

要解决此问题,您可以在MembershipUser DbSet中执行过滤:

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

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