使用急切加载时,实体框架是不是将所有相关实体加载到无限深度

Posted

技术标签:

【中文标题】使用急切加载时,实体框架是不是将所有相关实体加载到无限深度【英文标题】:Does Entity Framework load all related entities to unlimited depth when using eager loading使用急切加载时,实体框架是否将所有相关实体加载到无限深度 【发布时间】:2019-08-17 12:08:27 【问题描述】:

我尝试搜索,但在 docs.microsoft 上找不到确切答案:https://docs.microsoft.com/en-us/ef/core/querying/related-data#eager-loading

我有这段代码:

await MyDbContext.Users.Where(u => u.Id == Id).Include(u => u.UserContacts).ThenInclude(uC => uC.Contact);

返回类型是 User 类型,Contact 也是 User 类型。

当我调试并单步执行时,似乎所有必需的UserContacts 以及它们的所有Contacts 以及它们的所有Contacts 都已加载,等等.

问题:

    这是 EF 的预期行为吗?如果是的话,这不会影响性能吗?必须将 DB 查找到如此深度? 有没有办法让我指定一种“最大深度”?

与我在这里问的最接近的匹配可能是这个 SO 线程: How does Entity Framework work with recursive hierarchies? Include() seems not to work with it

【问题讨论】:

我找到了这个帖子:***.com/questions/53174003/…。答案表明它只是让我“瞥见”相关子代的调试器。不确定这是否就是全部,或者返回的对象是否实际上包含这些深度引用?还是一头雾水。 您可以检查结果查询是什么(它出现在输出窗口中)。这将只是用户表与自身的连接。您确定在之前的查询中没有在相同的上下文中加载用户吗?如果它们已经加载,那么即使您没有要求加载它们,您也会看到它们。 @JerMah 谢谢你。是的,我自己得到了用户表的连接。鉴于包含和关系,我希望如此。但是连接不是无限深度吗?也没有,因为我正在调试第一个查询,所以之前肯定没有加载其他用户。 【参考方案1】:

您可以在两种情况下导航到您的预加载查询未指定的实体:

导航属性修复

如果同一 DbContext 上的查询或先前查询已加载作为导航属性目标的实体,则更改跟踪器将“修复”导航属性。

延迟加载

显然,如果启用延迟加载,导航属性将在您访问它们时加载。

【讨论】:

谢谢大卫。可以肯定的是,此应用程序中没有启用延迟加载,因为如果我没有明确包含它们,我的导航属性将为空。 Fix-UP 会影响调试器吗?因为当我展开查看导航属性的详细信息时,它不会立即出现,而是调试器似乎需要时间来“评估”它。 这听起来像延迟加载。如果您有 IntelliTrace,您可以在调试时看到查询事件。 docs.microsoft.com/en-us/visualstudio/debugger/… 如果它确实是延迟加载,我应该能够在我的示例中不明确地使用Include,而是执行以下操作:var contacts = user?.UserContacts.ToList()。正确的?然而,这是行不通的。如果我尝试这样做,我会得到一个 Null 异常。调试器也不喜欢我检查 UserContacts 中的 User 对象,我在没有指定 Include 的情况下查询了该对象。 @David-Browne-Microsoft 好吧,事实证明,我没有明确要求的 Contacts 可能是由于另一个 Include 而导致我更进一步包含列表,其中可能加载了这些实体,使其看起来像是下降到无限深度。

以上是关于使用急切加载时,实体框架是不是将所有相关实体加载到无限深度的主要内容,如果未能解决你的问题,请参考以下文章

实体框架急切加载不返回数据,延迟加载有

代码优先实体框架。急切加载,验证然后保存导致错误

使用实体框架的表中的相关数据

实体框架上的急切加载导航属性

我正在尝试使用实体框架进行急切加载,其中我在区域和客户端之间具有一对多的关系

在 EFCore 急切加载 LINQ 查询中,如何在 ThenInclude() 表达式中引用***实体?