ASP.NET Core Web API中EF Core一对多表关联数据查询问题
解决EF Core中关联表数据为空的问题
核心原因
Entity Framework(EF)默认不会自动加载关联实体(比如Game的GameCharacters),除非主动指定加载策略。你的代码仅查询了Games表,未告知EF要同时获取对应的GameCharacter数据,因此返回的GameCharacters是空数组。
解决方案
1. 使用Include显式加载关联数据
修改GetGames方法,通过Include指定要包含的关联集合,EF会生成JOIN语句一次性查询所有关联数据:
[HttpGet] public async Task<IActionResult> GetGames() { var games = await dbContext.Games .Include(g => g.GameCharacters) .ToListAsync(); return Ok(games); }
2. 修复单个Game查询的参数错误
你的Game实体中GameID是int类型,但GetGame方法的参数用了Guid,这会导致FindAsync永远找不到数据。需将参数类型改为int,同时修正路由模板:
[HttpGet] [Route("{GameID:int}")] // 限制路由参数为int类型 public async Task<IActionResult> GetGame([FromRoute] int GameID) { var game = await dbContext.Games .Include(g => g.GameCharacters) .FirstOrDefaultAsync(g => g.GameID == GameID); if (game == null) { return NotFound(); } return Ok(game); }
注:用
FirstOrDefaultAsync代替FindAsync是因为FindAsync不支持链式调用Include,它仅能根据主键直接查找,不会加载关联数据。
3. 延迟加载注意事项(可选)
若想启用延迟加载,需满足两个条件:
- 关联属性(
Game.GameCharacters和GameCharacter.Game)已设为virtual(你的代码已满足) - 在DbContext配置中启用延迟加载代理:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("你的连接字符串") .UseLazyLoadingProxies(); }
但API场景不推荐使用延迟加载:序列化返回结果时,EF会尝试加载关联数据,但此时DbContext可能已释放,易引发异常,还会导致N+1查询问题(多次数据库请求)。
额外提示
GameCharacter实体中的CharGame字段属于冗余字段,可通过关联的Game实体获取Title,建议删除以避免数据不一致。
内容的提问来源于stack exchange,提问作者Basit
相关产品推荐
相关产品推荐

