Linq 查询加载时间过长

问题描述 投票:0回答:2

我有以下 linq 查询 -

IQueryable<VaccinationClinic> clinics = _appDbContext.VaccinationClinics
                .Include(h => h.HealthBoard)
                .Include(c => c.ClinicType)
                .Include(v => v.VaccinationAvailableTo)
                .Include(p => p.AdministrativeLead).ThenInclude(pn => pn.Title)
                .Include(d => d.ResponsibleSupervisingClinician).ThenInclude(dr => dr.Title)
                .Include(d => d.ResponsibleSupervisingClinician).ThenInclude(dr => dr.ProfessionalBodyDetails)
                .Include(r => r.Designations)
                .Include(t => t.Training)
                .Include(a => a.AnnualFigures).AsQueryable();

我们对结果进行搜索,例如-

if (searchCriteria == SearchCriteria.Designated)
{
   clinics = clinics.Where(CheckDesignationIsActive(designationNumberOfDays));
   clinics = clinics.Where(CheckDesignationIsActivePart2(designationNumberOfDays));
   clinics = clinics.Where(sp => !sp.DedesignationDate.HasValue);
}

与-

private Expression<Func<VaccinationClinic, bool>> CheckDesignationIsActive(int desNumOfDays)
{
   return sp => sp.Designations.OrderByDescending(r => r.DesignatedAt).FirstOrDefault().DesignatedAt.AddYears(sp.Designations.OrderByDescending(r => r.DesignatedAt).FirstOrDefault().NumberOfYears) >= DateTime.Now;
}

private Expression<Func<VaccinationClinic, bool>> CheckDesignationIsActivePart2(int desNumOfDays)
{
   return sp => !((sp.Designations.OrderByDescending(r => r.DesignatedAt).FirstOrDefault().DesignatedAt.AddYears(sp.Designations.OrderByDescending(r => r.DesignatedAt).FirstOrDefault().NumberOfYears) > DateTime.Now) &&
                            (sp.Designations.OrderByDescending(r => r.DesignatedAt).FirstOrDefault().DesignatedAt.AddYears(sp.Designations.OrderByDescending(r => r.DesignatedAt).FirstOrDefault().NumberOfYears) <= DateTime.Now.AddDays(desNumOfDays)));
}

然后在最后-

 var clinicList = await clinics.AsSplitQuery().ToListAsync();
 return clinicList;

主要的 linq 查询在我们添加搜索条件之前需要时间加载,有没有办法加快它的速度?

c# asp.net-mvc performance linq asp.net-core
2个回答
0
投票

我建议每次需要集合导航属性的值时避免使用 FirstOrDefault。它可以通过简单的连接来完成。我已经删除了你的辅助函数使用 - 它不能在没有第三方库的情况下在新查询中翻译。

if (searchCriteria == SearchCriteria.Designated)
{
   var clinicsWithDesignation = 
      from c in clinics
      from d in c.Designations
         .OrderByDescending(r => r.DesignatedAt)
         .Take(1)
      select new 
      {
         Clinic = c,
         Designation = d
      };

   clinicsWithDesignation = clinicsWithDesignation
      .Where(cd => cd.Designation.DesignatedAt.AddYears(cd.Designation.NumberOfYears) >= DateTime.Now);

   clinicsWithDesignation = clinicsWithDesignation
      .Where(cd => !((cd.Designation.DesignatedAt.AddYears(cd.Designation.NumberOfYears) > DateTime.Now) &&
                            (cd.Designation.DesignatedAt.AddYears(cd.Designation.NumberOfYears) <= DateTime.Now.AddDays(designationNumberOfDays))));

   clinics = clinicsWithDesignation.Select(cd => cd.Clinic);
   clinics = clinics.Where(sp => !sp.DedesignationDate.HasValue);
}

0
投票

我建议你 - 尝试在 SQL 事件探查器中检查它,你的包含这么多包含的查询是如何翻译的。我记得在过去的案例中(但它是 Entity Framework 6),我们在 SQL 分析器中看到我们的 .Include(...) 以某种方式转换为 SQL 中的 Union 操作。之后,我们决定直接通过 Entity Framework 重新处理带有连接的查询。我们开始制定一个规则,在一次查询中最多使用 2 次 .Include(...)

也尝试阅读 github 中的这篇文章: https://github.com/dotnet/efcore/issues/25731 他们正在解决包含太多内容的性能问题,并且还在解释为什么会这样。

© www.soinside.com 2019 - 2024. All rights reserved.