ABP.io仓储Repository中如何使用2个及以上WithDetails加载关联数据
问题场景
定义的Contract实体结构:
class Contract { public TenantProfile TenantProfile { get; set; } public ContractStatus Status { get; set; } }
服务层重写GetAsync(Id)方法时,最初编写的查询代码:
var contractWithDetails = (await Repository.WithDetailsAsync(x => x.Status)).FirstOrDefault(x => x.Id == id);
代码执行后TenantProfile属性值为null,原因是WithDetailsAsync不支持对IQueryable链式调用,单次调用仅加载传入的单个关联属性,无法满足同时加载2个及以上关联数据的需求。
解决方法
- 一次性给
WithDetailsAsync传入所有需要加载的导航属性选择表达式,无需链式调用。多数仓储封装的WithDetailsAsync方法都支持多参数传入,参数签名一般为params Expression<Func<TEntity, object>>[] includeExpressions,修改后的代码如下:
// 逗号分隔所有需要加载的关联导航属性即可 var contractWithDetails = (await Repository.WithDetailsAsync( x => x.Status, x => x.TenantProfile )).FirstOrDefault(x => x.Id == id);
- 如果你的仓储层支持先组装IQueryable再执行,可以直接基于EF Core原生的
Include方法链式配置所有需要加载的关联属性,最后执行查询,避免全表加载到内存后再过滤的性能问题,参考写法:
var contractQuery = Repository.AsQueryable() .Include(x => x.Status) .Include(x => x.TenantProfile); var contractWithDetails = await contractQuery.FirstOrDefaultAsync(x => x.Id == id);
注意:不要在调用
WithDetailsAsync加载全量关联数据到内存后,再执行FirstOrDefault做Id匹配,会导致全表扫描+全量数据加载,性能很差。
内容的提问来源于stack exchange,提问作者Aarnihauta
相关产品推荐
相关产品推荐

