EF Core 5.08懒加载下子集合正常加载但单导航属性被覆盖问题
问题原因
- 核心诱因是你在
Assignment的无参构造函数中主动初始化了Asset属性为全新的Asset实例。EF Core从数据库加载Assignment实体时,会先调用无参构造函数创建对象,此时Asset已经被赋值为一个新生成、携带随机Guid的实例。 - 你当前的查询逻辑既没有显式加载
Asset导航属性,也没有触发懒加载逻辑:通过context.Workspaces.Find(workspaceId)拿到Workspace后直接返回其Assignments集合,这个过程EF Core只会加载Assignment的普通字段(包括AssetId外键),不会主动处理Asset导航属性的加载。 People导航属性正常是因为你仅在构造函数中初始化了空的集合实例,EF Core的关系修复、懒加载逻辑可以正常向集合中填充数据,不会产生冲突;但Asset是单个引用对象,EF Core检测到该属性已经被赋值为自定义实例后,既不会用外键对应的数据库记录覆盖该值,也不会触发懒加载拉取关联数据,所以你拿到的永远是构造函数里new出来的全新实例。
修复方案
- 删除
Assignment构造函数中对Asset属性的初始化代码,仅保留集合类型导航属性的初始化即可:
public Assignment(){ this.AssignmentId = Guid.NewGuid(); // 移除 this.Asset = new Asset(); 行 this.People = new List<Person>(); }
- 调整查询逻辑,显式加载关联导航属性,避免依赖懒加载带来的上下文生命周期风险(Blazor Server场景下DbContext生命周期配置不当很容易出现懒加载时上下文已释放的问题):
public List<Assignment> Get(Guid workspaceId) { return context.Workspaces .Where(w => w.WorkspaceId == workspaceId) .SelectMany(w => w.Assignments) .Include(a => a.Asset) .Include(a => a.People) .ToList(); }
- 修正异步方法的错误写法,不要用
Task.Run包装同步查询,直接使用EF Core原生异步方法减少不必要的线程池开销:
public async Task<List<Assignment>> GetAsync(Guid workspaceId) { return await context.Workspaces .Where(w => w.WorkspaceId == workspaceId) .SelectMany(w => w.Assignments) .Include(a => a.Asset) .Include(a => a.People) .ToListAsync(); }
内容的提问来源于stack exchange,提问作者juststressed
相关产品推荐
相关产品推荐

