我有以下 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 查询在我们添加搜索条件之前需要时间加载,有没有办法加快它的速度?
我建议每次需要集合导航属性的值时避免使用 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);
}
我建议你 - 尝试在 SQL 事件探查器中检查它,你的包含这么多包含的查询是如何翻译的。我记得在过去的案例中(但它是 Entity Framework 6),我们在 SQL 分析器中看到我们的 .Include(...) 以某种方式转换为 SQL 中的 Union 操作。之后,我们决定直接通过 Entity Framework 重新处理带有连接的查询。我们开始制定一个规则,在一次查询中最多使用 2 次 .Include(...)
也尝试阅读 github 中的这篇文章: https://github.com/dotnet/efcore/issues/25731 他们正在解决包含太多内容的性能问题,并且还在解释为什么会这样。