优化慢速LINQ查询

ara*_*zzy 5 c# linq performance entity-framework

我有一个LINQ查询,我在优化时遇到问题,大约需要5.5秒才能运行。我正在使用一个名为StaffingResourceData的视图和一个名为StaffingForecasts的表。

每个StaffingResource都有一个ResourceId,一个Division和一个Type。StaffingForecast具有ResourceId,项目,日期(代表一周中的星期一),小时。一个StaffingResource可以具有0个多个StaffingForecast。

对于每个StaffingResource,我都需要一个其未来12周的预计总工作时间的列表。这是我现在所拥有的:

// Get list of dates
var dates = new List<DateTime>();
var start = Utilities.GetStartOfWeek(DateTime.Today);
for (var i = 0; i < 12; i++)
{
    dates.Add(start.AddDays(i * 7));
}
var end = dates[11];

// Get resources
var resources = (from r in context.StaffingResourceDatas
                 where r.EmployeeId != null
                     && !exclusionList.Contains(r.ResourceTitleId)
                 join f in context.StaffingForecasts.Where(x => x.Date >= start && x.Date <= end) on r.ResourceId equals f.ResourceId into g1
                 from f in g1.DefaultIfEmpty()
                 group new { f.Date, f.Hours } by r into g2
                 select new ChartResourceModel
                 {
                     ResourceId = g2.Key.ResourceId,
                     Division = g2.Key.ResourceDivision,
                     Type = g2.Key.ResourceType,
                     Dates = dates.Select(d => new ChartDateModel
                     {
                         Date = d,
                         Available = (g2.Where(f => f.Date == d).Any() ? g2.Where(f => f.Date == d).Sum(f => f.Hours) : 0) < 24
                     }).ToList()
                 })
               .ToList();
Run Code Online (Sandbox Code Playgroud)

关于如何加快速度的任何想法?

Ste*_*pUp 7

  1. 避免使用Contains。它会严重降低性能。看到这个帖子

  2. ToList()是执行查询的命令。直到您调用ToList()方法,由于linq具有称为延迟执行的功能,因此不会启动linq查询。因此,如果调用ToList(),您将使用Databaseof文件开始一些实际操作。

  3. 减少表的列可减少所需的带宽(从查询中删除不必要的列)
  4. 关闭更改跟踪和身份管理(例如,LINQ-to-SQL中的ObjectTrackingEnabled)

    using (YourDataContext dataContext = new YourDataContext())    
    {
        dataContext.ObjectTrackingEnabled = false;    
        //Your code
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 使用EF的调整选项之一,例如.AsNoTracking()在这里可以看到详细的描述。
  6. 使用预编译的查询。有时可以减少预处理开销