Linq渴望加载链实体

时间:2018-03-29 01:34:47

标签: linq entity-framework-core eager-loading

为什么candidate.Qualification在以下所有尝试中始终为空:

var candidate = await _acceptedOfferRepository.GetAll()
                                              .Include(c => c.Candidate)
                                              .Where(ao => ao.Candidate.Id == candidateId && ao.EmployerId.Id == employerId)
                                              .Select(c => c.Candidate)
                                              .Include(c => c.Qualification)
                                              .FirstOrDefaultAsync();

或者:

var candidate = await _acceptedOfferRepository.GetAll()
                                              .Include(c => c.Candidate.Qualification)
                                              .Where(ao => ao.Candidate.Id == candidateId && ao.EmployerId.Id == employerId)
                                              .Select(c => c.Candidate)
                                              .FirstOrDefaultAsync();

或者:

var candidate = await _acceptedOfferRepository.GetAll()
                                              .Include(c => c.Candidate)
                                              .ThenInclude(c => c.Candidate.Qualification)
                                              .Where(ao => ao.Candidate.Id == candidateId && ao.EmployerId.Id == employerId)
                                              .Select(c => c.Candidate)
                                              .FirstOrDefaultAsync();
  • 候选人和他/她之间有1:1的关系 资格

  • _acceptedOfferRepository.GetAll()返回 IQueryable的

我认为FirstOrDefaultAsync()之前的Select()出了问题。一旦我删除它工作正常,所有链接的实体都正确加载。但是它返回第一个AcceptedOffer,而我需要候选人!

2 个答案:

答案 0 :(得分:1)

失败尝试的查询属于Ignored includes类别:

  

如果更改查询以使其不再返回查询开头的实体类型的实例,则忽略包含运算符。

它们非常类似于链接中的示例。查询以AcceptedOffer开头,然后Select将结果类型更改为Candidate,因此只会忽略所有Include / ThenInclude

我建议的第一件事是配置EF Core为被忽略的包括抛出异常,如链接中所述:

optionsBuilder.ConfigureWarnings(warnings => warnings
    .Throw(CoreEventId.IncludeIgnoredWarning));

其次,尝试构建实体,从要返回的实体开始返回查询。例如,对于您的示例,它可能是这样的(如果您具有从CandidateAcceptedOffer和相应存储库的反向导航属性:

var candidate = await _candidateRepository.GetAll()
    .Include(c => c.Qualification)
    .Include(c => c.AcceptedOffers) // optional
    .Where(c => c.Id == candidateId && 
        c.AcceptedOffers.Any(ao => ao.EmployerId.Id == employerId))
    .FirstOrDefaultAsync();

答案 1 :(得分:0)

这很好用:

var candidate = (await _acceptedOfferRepository.GetAll()
                                          .Include(c => c.Candidate)
                                          .ThenInclude(c => c.Candidate.Qualification)
                                          .Where(ao => ao.Candidate.Id == candidateId && ao.EmployerId.Id == employerId)
                                          .FirstOrDefaultAsync())?.Candidate;

但仍然不太确定为什么Select()没有加载Qualification!