优化EntityFramework查询

本文关键字:查询 EntityFramework 优化 | 更新日期: 2023-09-27 18:06:18

我有2个表- ReferrerSources大小为50行,Referrer大小为150万行。

每个Refferer实体都有对应ReferrerSource的链接。我只需要为每个ReferrerSource计算Referrer的数量:

public void CreateConvertionReportTest(DateTime from, DateTime to)
{
    //.GetAll() returns IQueryable<T>. It's equal to Context.Set<T>().
    var src = ContextManager.ReferrerSourceContext.GetAll();
    var reff = ContextManager.ReferrerContext
                             .GetAll()
                             .Where(r => r.Created >= from && r.Created < to);
    var info = src.GroupJoin(
                   reff, 
                   (s) => s.Id, 
                   (r) => r.ReferrerSourceId, 
                   (s, or) => new
                   {
                       sorce = s.Name,
                       refferrersCount = or.Count()
                   } 
               );
    foreach(var g in info)
        Console.WriteLine("src: " + g + " : " + g.refferrersCount);
}

但是这段代码在执行30秒后会导致TimeoutException

我知道,简单的SQL脚本可以在一瞬间做到这一点。我做错了什么?

优化EntityFramework查询

你只需要投影来解决这个问题,我没有你的代码所以这是我自己使用我自己的存储库的一个例子但是EF部分保存得很好,因为我使用了iquerable:

var companyList = _companyRepo
            .Query()
            .Select(c => new
            {
                label = c.Name,
                count = c.Projects.Count
            }).ToList();

我认为/希望你能把它转化为你的需要。根据我对你的问题的理解,这返回一个公司列表和每个公司拥有的项目数量,在我的数据模型中,一个公司可以有许多项目,因此在公司和项目之间有一个导航属性。如果您使用导航属性作为开头,则不需要连接。

检查数据库中Referer表上的索引。在referersource的外键上应该有一个索引。

你可以使用sql server profiler来检查哪些查询被执行。在分析器中手动执行这些查询,并让它们得到优化。它也会显示缺失的指数。但是我有一种感觉,我上面提到的索引是缺失的。

如果你已经正确设置了导航属性,如果我理解你的模型,你应该可以这样做:

var src = ContextManager.ReferrerSourceContext.GetAll()
    Select(x => new 
    {
        Source = x.Name,
        RefferersCount = x.Refferers
            .Where(r => r.Created >= from && r.Created < to)
            .Count()
    });
foreach(var source in src)
{
    Console.WriteLine("src: " + source.Name + " : " + RefferersCount);
}