Lambda Sum子查询返回结果不正确,如何正确实现嵌套子查询求和?
问题核心原因
你代码的问题根源是子查询与外层查询的Lambda参数变量名冲突,导致关联条件逻辑完全不符合预期。
外层Select的参数命名为x,内层Where查询ItemCheckListResults的参数也命名为x,此时x.TemplatePMPResultId.Equals(x.Id)的判断逻辑,实际变成了「ItemCheckListResults的TemplatePMPResultId等于自身的Id」,而非你预期的「ItemCheckListResults的TemplatePMPResultId等于外层TemplatePMPResult记录的Id」,所以只会匹配到极少数符合这个错误条件的记录,表现为仅返回第一条符合条件的记录值。你单独拿生成的SQL修改ID后执行正常,是因为手动修改ID时已经修正了错误的关联条件,所以结果才符合预期。
修复方案
这种嵌套子查询的写法本身是完全可行的,只需要修改内层Lambda的参数名,避免和外层参数冲突即可:
public Task<IQueryable<TemplatePMPResultViewModel>> GetTemplatePMPResultViewModel() { var result = _dbSet.Select(x => new TemplatePMPResultViewModel { Id = x.Id, InsertDate = x.InsertDate, Latitude = x.Latitude, Longitude = x.Longitude, CompanyAssetName = x.TemplatePMP.CompanyAsset.CodeAsset, ConstructionSiteName = x.ConstructionSite.Name, MechanicName = x.Mechanic.Name, SupervisorName = x.Supervisor.Name, // 内层参数重命名为c,避免和外层x冲突 Points = _dbContext.ItemCheckListResults.Where(c => c.TemplatePMPResultId.Equals(x.Id)).Sum(c => c.Points), PendingPoints = _dbContext.ItemCheckListResults .Where(c => c.TemplatePMPResultId.Equals(x.Id) && c.ExecuteActionPlan && (c.EndDate ?? DateTime.MaxValue) <= DateTime.Now) .Sum(c => c.Points), RegionName = x.ConstructionSite.Region.Name, TypeName = x.TemplatePMP.CompanyAsset.Group.GroupType.Description }); return Task.FromResult(result); }
可选优化方案
如果要进一步简化写法、提升性能,可以参考两种方案:
- 配置导航属性:如果TemplatePMPResult实体已经配置了和ItemCheckListResults的一对多导航属性(比如属性名就叫ItemCheckListResults),可以直接调用导航属性求和,不需要手动访问DbSet,写法更简洁也不容易出现变量名冲突问题:
Points = x.ItemCheckListResults.Sum(c => c.Points) - 分组聚合关联:如果数据量较大,可以先对ItemCheckListResults按TemplatePMPResultId分组求和,再和主表关联,避免每条主记录都执行一次子查询,大幅提升查询性能。
内容的提问来源于stack exchange,提问作者Raphael Lima
相关产品推荐
相关产品推荐

