人们要求我修复 N+1 错误?

Cra*_*aig 3 c# linq-to-sql

我从未听说过,但人们将应用程序中的问题称为“N+1 问题”。他们正在做一个基于 Linq to SQL 的项目,有人发现了一个性能问题。我不太明白 - 但希望有人能引导我。

似乎他们正在尝试获取 obects 列表,然后在此之后的 Foreach 导致过多的数据库命中:

据我了解,源代码的第二部分仅在 forwach 中加载。

因此,加载的项目列表:

var program = programRepository.SingleOrDefault(r => r.ProgramDetailId == programDetailId);
Run Code Online (Sandbox Code Playgroud)

然后,我们使用这个列表:

foreach (var phase in program.Program_Phases)
{
    phase.Program_Stages.AddRange(stages.Where(s => s.PhaseId == phase.PhaseId));
    phase.Program_Stages.ForEach(s =>
    {
         s.Program_Modules.AddRange(modules.Where(m => m.StageId == s.StageId));
    });
    phase.Program_Modules.AddRange(modules.Where(m => m.PhaseId == phase.PhaseId));
}
Run Code Online (Sandbox Code Playgroud)

似乎确定的问题是,他们希望“程序”包含它的孩子。但是当我们在查询中引用孩子时,它会重新加载程序:

program.Program_Phases
Run Code Online (Sandbox Code Playgroud)

他们期望程序完全加载并在内存中,并且分析器似乎表明该程序表,所有连接都在每个“foreach”上被调用。

这有意义吗?

(编辑:我找到了这个链接: linq to sql 会自动延迟加载关联实体吗? 这可能会回答我的问题,但是 .. 他们正在使用更好的 (where person in...) 符号,而不是这个奇怪的 (x => x....)所以如果这个链接是答案——也就是说,我们需要“加入”查询——可以做到吗?)

mtr*_*udt 5

在 ORM 术语中,“N+1 选择问题”通常发生在具有嵌套集合属性的实体时。它是指使用延迟加载时将实体数据完全加载到内存中所需的查询数。通常,查询越多,从客户端到服务器的往返次数就越多,服务器处理查询所需的工作也就越多,这会对性能产生巨大影响。

有多种技术可以避免这个问题。我不熟悉 Linq to SQL,但 NHibernate 支持在某些情况下有帮助的急切获取。如果您不需要加载整个实体实例,那么您还可以考虑进行投影查询。另一种可能性是更改您的实体模型以避免嵌套集合。