EF Core 6未用Include却默认加载关联实体致JSON循环引用错误求助
问题分析与解决方案
为什么没加Include却自动加载了导航属性?
这是因为EF Core的延迟加载被启用了。当满足以下两个条件时,EF Core会自动触发延迟加载:
- 实体类的导航属性(比如
CreatedBy、AssetsCategoryCreatedList)被声明为virtual - 项目中启用了延迟加载代理(比如在
AddDbContext时调用了.UseLazyLoadingProxies(),或者安装了Microsoft.EntityFrameworkCore.Proxies包)
当API序列化查询结果时,会访问到CreatedBy属性,触发延迟加载加载对应的Users实体;接着序列化Users时又访问到AssetsCategoryCreatedList,再次触发延迟加载加载关联的AssetsCategoryMaster集合,如此循环往复,就会出现JSON序列化的循环引用错误。
解决步骤
1. 关闭不必要的延迟加载
根据你的需求,有两种方式可以阻止自动加载导航属性:
方式一:禁用延迟加载代理
在Program.cs的数据库上下文配置中,移除或关闭UseLazyLoadingProxies:builder.Services.AddDbContext<YourDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("YourConnString")) .UseLazyLoadingProxies(false)); // 显式关闭,或者直接去掉.UseLazyLoadingProxies()方式二:将导航属性改为非
virtual
修改实体类的导航属性,去掉virtual关键字,EF Core就不会为这些属性生成延迟加载代理:// AssetsCategoryMaster类 public Users CreatedBy { get; set; } // 去掉virtual // Users类 public ICollection<AssetsCategoryMaster> AssetsCategoryCreatedList { get; set; } // 去掉virtual
2. 解决JSON循环引用问题
即使关闭了延迟加载,为了避免后续其他场景出现类似问题,建议配置JSON序列化忽略循环引用:
在Program.cs中添加JSON序列化选项配置:
builder.Services.AddControllers() .AddJsonOptions(options => { // 忽略循环引用,序列化时遇到循环会自动跳过 options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; // 可选:如果需要保留引用关系,可以用ReferenceHandler.Preserve,会生成$id等标识字段 // options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve; });
3. 推荐使用DTO(数据传输对象)
更规范的做法是创建DTO类,只包含API需要返回的字段,避免直接序列化实体类。比如:
public class AssetsCategoryDto { public int Id { get; set; } public string AssetCategoryName { get; set; } // 只包含需要的CreatedBy信息,比如用户名 public string CreatedByUserName { get; set; } // 不要包含双向导航的集合属性 }
查询时将实体映射到DTO返回:
var assetCategoryList = await _context.Set<AssetsCategoryMaster>() .Where(p => !p.IsDeleted) .Select(p => new AssetsCategoryDto { Id = p.Id, AssetCategoryName = p.AssetCategoryName, CreatedByUserName = p.CreatedBy.UserName }) .ToListAsync(); return Ok(assetCategoryList);
这种方式不仅能彻底解决循环引用问题,还能减少数据传输量,提升API安全性。
内容的提问来源于stack exchange,提问作者Suresh M
相关产品推荐
相关产品推荐

