EF Core - 为啥“无限”嵌套急切加载?
Posted
技术标签:
【中文标题】EF Core - 为啥“无限”嵌套急切加载?【英文标题】:EF Core - why 'infinate' nested eager loading?EF Core - 为什么“无限”嵌套急切加载? 【发布时间】:2021-01-26 06:29:07 【问题描述】:我有两个实体之间的一对多关系:地图和地图节点。当我渴望用 Maps 加载 MapNodes(通过 Include())时,我得到 Map,我得到相关的 MapNodes,但在相关的 MapNodes 中,我也再次得到完整的父 Map。然后该地图(再次)具有关联的 MapNode,依此类推......
我需要将查询的内容限制在一个级别(即 MapNodes),而不是让预加载更深入。
[Table("maps")]
public partial class Maps
public Maps()
MapNodes = new HashSet<MapNodes>();
<...>
[InverseProperty("Map")]
public virtual ICollection<MapNodes> MapNodes get; set;
[Table("map_nodes")]
public partial class MapNodes
public MapNodes()
<...>
[Column("map_id", TypeName = "int(10) unsigned")]
public uint MapId get; set;
public Maps Map get; set;
当我执行以下查询时:
var map = await context.Maps.Include( x => x.MapNodes).FirstOrDefaultAsync( x => x.Id == id);
我得到一个无限的急切加载:
"id": 1063,
"mapNodes": [
"id": 25784,
"mapId": 1063,
"map":
"id": 1063,
"mapNodes": [
"id": 25784,
"mapId": 1063,
"map":
"id": 1063,
"mapNodes": [
...
【问题讨论】:
这称为Reference Loop Handling
。 System.Text.Json
尚不可用。但它在Microsoft.AspNetCore.Mvc.NewtonsoftJson
中可用在您的startup
中,您可以通过AddControllersWithViews().AddNewtonsoftJson()
和x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
进行配置。
谢谢!你能发布一个解决方案吗?我会“接受”它。
如果您查询相关实体(使用Include
),EF 生成的对象将始终包含循环引用。在将数据发送到客户端之前,创建一组类来表示平面数据(Response/DTO/ViewModel 对象)并将实体/模型对象映射到这些类,而不是直接发送查询结果,这是一个更好的选择。
【参考方案1】:
Microsoft 将 ASP.NET Core 3 中的 Microsoft.AspNetCore.Mvc.NewtonsoftJson
替换为他们自己的实现,即 System.Text.Json
,但它还不支持 Reference Loop Handling
处理。
所以为了配置Reference Loop Handling
,你需要为Microsoft.AspNetCore.Mvc.NewtonsoftJson
添加nuget包,然后这样配置:
services.AddControllersWithViews().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
);
【讨论】:
以上是关于EF Core - 为啥“无限”嵌套急切加载?的主要内容,如果未能解决你的问题,请参考以下文章
EF CTP5 - 强类型急切加载 - 如何包含嵌套导航属性?
.NET Core/EF Core 2.0 升级后急切加载“类型之间未定义强制运算符”
EF Core 5.0.4 - 从核心 3.1 升级后,通过 Include() 的急切加载不起作用