.NET Core查询Blog模型时关联Paragraph列表为空问题咨询
问题原因
这是EF Core的默认机制导致的:EF Core默认不会自动加载导航属性对应的关联表数据,具体对应你的场景有几个直接原因:
Find()方法仅会查询Blog主表的字段,不会自动关联查询Paragraph、Company两张关联表- 虽然你给导航属性加了
virtual关键字,但如果没有额外配置懒加载,懒加载机制不会自动生效 - 你初始化了
Paragraphs为new List<Paragraph>(),所以未加载到数据时返回空数组,Company没有初始化所以返回null,和你实际拿到的返回结果完全匹配
解决方法
方法1:使用Include预加载关联属性(最推荐,性能最优)
这是Web接口场景最常用的方案,主动指定需要关联查询的属性,一次性拉取所有需要的数据,不会产生额外的数据库查询。
首先引入命名空间:
using Microsoft.EntityFrameworkCore;
修改你的查询代码即可:
[HttpGet] [Route("api/[controller]/{id}")] public IActionResult GetById(int id) { var findBlog = _db.Blog .Include(b => b.Paragraphs) .Include(b => b.Company) .FirstOrDefault(b => b.Id == id); if (findBlog == null) { return NotFound("Blog not found"); } return new JsonResult(findBlog); }
方法2:显式加载关联属性
适合需要按需加载关联数据的场景,先查询主表数据,再手动加载关联属性,会额外产生两次数据库查询:
[HttpGet] [Route("api/[controller]/{id}")] public IActionResult GetById(int id) { var findBlog = _db.Blog.Find(id); if (findBlog == null) { return NotFound("Blog not found"); } // 手动加载集合类型的导航属性 _db.Entry(findBlog).Collection(b => b.Paragraphs).Load(); // 手动加载单对象类型的导航属性 _db.Entry(findBlog).Reference(b => b.Company).Load(); return new JsonResult(findBlog); }
方法3:开启懒加载(不推荐Web接口场景使用)
如果要使用懒加载需要额外配置,但是这种方案容易产生N+1查询的性能问题,且序列化时如果上下文释放会直接报错,非特殊需求不建议使用:
- 安装Nuget包:
Microsoft.EntityFrameworkCore.Proxies - 在DbContext的
OnConfiguring方法中开启懒加载代理:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseLazyLoadingProxies() .UseSqlServer("你的数据库连接字符串"); }
额外注意事项
返回JSON时大概率会遇到循环引用报错(Paragraph类中的Blog导航属性会反向引用Blog对象,形成循环),需要配置JSON序列化忽略循环引用,.NET 6+版本在Program.cs中添加如下配置即可:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; });
内容的提问来源于stack exchange,提问作者Deybi Tabora Paz
相关产品推荐
相关产品推荐

