添加实体时加载关联数据——Entity Framework Core 2技术问询
问题
在添加实体时,Add方法返回的EntityEntry对应的实体不包含任何关联数据。我使用了如下代码:
public async Task<Category> Add(Category model) { var entityEntry = await _applicationContext.Categories.AddAsync(model); await entityEntry.Reference(x => x.Parent).LoadAsync(); await _applicationContext.SaveChangesAsync(); return entityEntry.Entity; }
但据我理解这属于延迟加载数据,请问是否有更优的实现方式?
解决方案解析
其实你这里用的LoadAsync()属于显式加载,不是延迟加载哦——延迟加载是访问导航属性时自动触发数据库查询,而显式加载是你主动调用方法去加载关联数据。针对你的添加实体场景,有几种更优雅的实现方案:
1. 复用传入Model的关联数据(最优性能)
如果你的model对象本身已经携带了Parent的完整数据(比如前端传入时已包含Parent信息,或者你在调用Add方法前已经获取到了Parent实体),那完全不需要额外执行数据库查询,直接返回即可。EF Core在跟踪实体后会自动维护关联关系:
public async Task<Category> Add(Category model) { _applicationContext.Categories.Add(model); await _applicationContext.SaveChangesAsync(); return model; // 若model原本包含Parent数据,会直接保留 }
这种方式没有额外数据库开销,是最推荐的方案。
2. 手动查询关联实体并赋值(灵活性更高)
如果传入的model只携带了Parent的ID,没有完整的Parent实体数据,你可以先主动查询Parent,再赋值给新添加的Category,逻辑更直观:
public async Task<Category> Add(Category model) { if(model.ParentId.HasValue) { // 可根据需求添加过滤条件,比如只加载未标记删除的Parent model.Parent = await _applicationContext.Categories.FindAsync(model.ParentId); } _applicationContext.Categories.Add(model); await _applicationContext.SaveChangesAsync(); return model; }
这种方式能让你完全控制关联数据的加载逻辑,适合需要对关联实体做额外校验或过滤的场景。
3. 优化显式加载的写法(原方案的改进版)
如果你确实需要用显式加载,也可以调整写法让代码更简洁清晰,本质和你原来的实现一致,但可读性更好:
public async Task<Category> Add(Category model) { var addedCategory = (await _applicationContext.Categories.AddAsync(model)).Entity; await _applicationContext.Entry(addedCategory).Reference(x => x.Parent).LoadAsync(); await _applicationContext.SaveChangesAsync(); return addedCategory; }
需要注意的是,显式加载会额外发起一次数据库查询,所以尽量只在必要时使用。
小提醒
Include方法通常用于查询场景,添加实体时无法直接用它来加载关联数据,因为刚添加的实体还未持久化到数据库中,所以不要尝试在Add操作中使用Include哦。
内容的提问来源于stack exchange,提问作者tehabstract
相关产品推荐
相关产品推荐

