如何使用 EF Core 3.0 使多个包含更高效

Posted

技术标签:

【中文标题】如何使用 EF Core 3.0 使多个包含更高效【英文标题】:How to make multiple includes more efficient with EF Core 3.0 【发布时间】:2020-02-24 19:37:32 【问题描述】:

我有一个多层次的查询,包括:

var itemsToday = DatabaseContext.Items
                .Where(f => f.StartTime > DateTime.Today && f.StartTime < DateTime.Today.AddDays(1))
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType1)
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType2)
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType3)
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType4)
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType5)
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType6)
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType7)
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType8)
                .Include(x => x.LocalStats).ThenInclude(x=>x.StatType9)
                .Include(x => x.LocalDetails)
...
                .OrderBy(f=>f.SomeOrderingCriterion);

还有比这更多的包含。当然,这会导致 EF Core 3.0 在 SQL 查询中生成 许多 连接,这意味着它需要永远执行(检索 200 条记录需要 25 多秒)。

我试过用.Include(x =&gt; x.LocalStats.StatType1)的格式代替Include和ThenInclude,但是结果是一样的。

有什么方法可以提高效率吗?文档建议:

具有大量 Include 运算符的 LINQ 查询可能需要分解为多个单独的 LINQ 查询,以避免笛卡尔爆炸问题。

但我没有看到任何关于如何实际完成此操作的解释。

【问题讨论】:

@Silvermind 我不确定我是否完全理解你所说的,但我确实需要我包含的所有数据。有些东西我没有包括在内,因为我现在不需要它们。不幸的是,这些对象又大又复杂。 here 是他们的愿景,根据Breaking Changes - Eager loading of related entities now happens in a single query @thedarkspoon 我猜它会生成左连接?左连接太多,无法正确优化查询,这就是性能体验不佳的原因。 @thedarkspoon 你对此有什么了解吗?我也想知道有什么替代方法,因为以前的版本确实整合了这些类型的 JOIN。 @Siege21x 查看我刚刚发布的答案 :) 【参考方案1】:

最终我手动编写了 SQL,但我找不到使生成的 SQL 足够高效的方法。还可以考虑考虑优化数据库,例如添加聚集索引。这大大减少了数据库时间。

【讨论】:

【参考方案2】:

您应该考虑延迟加载此查询。

https://docs.microsoft.com/en-us/ef/core/querying/related-data

【讨论】:

以上是关于如何使用 EF Core 3.0 使多个包含更高效的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 FromSqlRaw 在 EF Core 3.0 中调用存储过程

在遍历 EF Core 5 中的多个条件包含后查询任何条目

EF Core 3.0 手动设置连接字符串

EF Core 调用具有多个连接的存储过程并映射相关数据

如何使 EF-Core 使用 Guid 而不是 String 作为其 ID/主键

具有 ASP.NET Core 3.0 和 EF Core 的多租户应用程序