You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 02:25:52