EF Core内存数据库查询实体时集合导航属性为空问题求助
问题根因
你遇到的StatedDates集合为空的问题由两个核心错误共同导致:
- 缺失关联集合的显式加载配置
EF Core默认不会自动加载实体的关联导航属性,你在ApprovedApplicationsInCurrentYearToToday方法的查询中,仅通过Include加载了Applicant导航属性,完全没有声明要加载StatedDates子集合,再加上你用了AsNoTracking关闭了变化追踪,EF不会自动补拉关联数据,最终取到的StatedDates就是实体类初始化时的空集合。 AsParallel()调用位置错误
你在EF Core的IQueryable还未执行、仍处于数据库查询翻译阶段时就调用了AsParallel(),这会直接将后续逻辑切换为PLINQ内存查询,EF Core的查询翻译、关联属性填充逻辑都会失效:不仅会把全量Applications表数据拉到内存中过滤,性能极差,还会直接中断导航属性的加载流程,哪怕写了Include也可能不生效。
额外注意:EF Core的DbContext本身不是线程安全的,在未完成查询执行就进入并行逻辑,还可能触发上下文并发访问的异常。
修复方案
按照以下步骤调整代码即可解决问题:
- 给查询补充
StatedDates导航属性的Include声明,所有需要用到的关联数据必须显式配置加载。 - 调整
AsParallel()的调用位置:必须等EF查询完全执行、数据加载到内存之后(即调用ToList()/ToArray()等执行方法后),再切换到并行逻辑做内存计算。 - (可选修正)你当前的
ApprovedApplicationsInCurrentYearToToday方法名明确是查询已审批的申请,但过滤逻辑中缺失了Status == ApplicationStatus.Approved的判断,会把其他状态的申请也统计进去,建议补上。
修正后的查询方法代码参考:
private IEnumerable<Domain.Entities.Application> ApprovedApplicationsInCurrentYearToToday(string userId) { var now = _dateTime.Now(); var currentYear = now.Year; // 先构造EF数据库查询,完成所有过滤、关联加载配置 var efQuery = _context.Applications .Include(app => app.Applicant) .Include(app => app.StatedDates) // 补全缺失的子集合加载 .AsNoTracking() .Where(app => app.Applicant.Id == userId && app.Status == ApplicationStatus.Approved // 补全审批状态过滤 && app.StatedDates.Any(date => date.Year == currentYear && date < now)); // 执行查询将数据加载到内存后,再切换为并行逻辑做后续处理 return efQuery.ToList().AsParallel(); }
补充注意事项:
- 不要在并行查询逻辑中触发EF的延迟加载,否则大概率出现线程安全异常、关联数据缺失的问题,所有需要用到的数据必须在查询执行阶段一次性加载完成。
- 如果你使用EF Core 6+,可以在调试时开启
EnableSensitiveDataLogging和EnableDetailedErrors,能更直观看到查询翻译、关联加载的问题。
内容的提问来源于stack exchange,提问作者Intolighter
相关产品推荐
相关产品推荐

