如何仅使用Include预加载ICollection的子级属性?
解决方案
1. EF Core:使用ThenInclude实现链式预加载
原有仓储的参数类型Expression<Func<Loan, object>>[]无法支持嵌套导航属性的预加载逻辑,需将参数改为Func<IQueryable<Loan>, IQueryable<Loan>>[],以此传入包含Include和ThenInclude的完整查询构建逻辑:
修改后的仓储层代码
public Loan LoadByLoanNumberWithRequiredData(string loanNumber, params Func<IQueryable<Loan>, IQueryable<Loan>>[] includes) { var query = Context.Loans.AsQueryable(); foreach (var include in includes) { query = include(query); } return query.FirstOrDefault(l => l.LoanNumber == loanNumber); }
业务层调用示例
Loan loan = LoanUnitOfWork.LoanRepository.LoadByLoanNumberWithRequiredData( loanNumber, q => q.Include(l => l.LoanStatuses).ThenInclude(ls => ls.Status) );
此方式可一次性预加载LoanStatuses及其关联的Status属性,彻底避免N+1查询问题。
2. EF6及更早版本:使用字符串路径重载Include
EF6及更早版本不支持ThenInclude,可通过指定字符串形式的嵌套导航路径实现预加载:
业务层调用示例
Loan loan = LoanUnitOfWork.LoanRepository.LoadByLoanNumberWithRequiredData( loanNumber, l => l.LoanStatuses, "LoanStatuses.Status" );
注意:字符串路径无编译时校验,需确保拼写正确。
3. 兼容方案:使用Select指定嵌套属性
若不想修改仓储方法的参数类型,可通过Select表达式指定集合导航属性的子属性:
业务层调用示例
Loan loan = LoanUnitOfWork.LoanRepository.LoadByLoanNumberWithRequiredData( loanNumber, l => l.LoanStatuses.Select(ls => ls.Status) );
此方式在EF6及EF Core中均支持,但仅适用于嵌套层级较少的场景。
内容的提问来源于stack exchange,提问作者sebastian whiffen
相关产品推荐
相关产品推荐

