如何在Entity Framework GroupBy查询结果中包含关联属性值
解决方案
方案1:复合键分组(兼容EF Core 5/6,性能最优)
因为同一个LocationId对应的LocationName完全一致,你可以直接将两个字段作为分组键,EF可以直接翻译为SQL的GROUP BY LocationId, LocationName,分组结果和仅按LocationId分组完全相同,无额外性能损耗:
var revenues = await _context.SaleTransaction .GroupBy(s => new { s.LocationId, s.Location.LocationName }) .Select(x => new LocationDTO { LocationId = x.Key.LocationId, LocationName = x.Key.LocationName, Revenues = x.Sum(i => i.Amount) }).ToListAsync();
方案2:EF Core 6+ 原生支持非分组键投影
EF Core 6开始已经支持翻译GroupBy后的First()方法(当字段和分组键一一对应时),你原本尝试的写法无需修改、不用加载全量数据到内存就可以直接运行:
var revenues = await _context.SaleTransaction .GroupBy(s => s.LocationId) .Select(x => new LocationDTO { LocationId = x.Key, LocationName = x.Select(i => i.Location.LocationName).First(), Revenues = x.Sum(i => i.Amount) }).ToListAsync();
方案3:分组后关联Location表(兼容所有EF Core版本,扩展性强)
如果需要从Location表取多个额外字段,可以先完成营收聚合再关联Location表,全程仅触发一次数据库请求,聚合后的数据量极小,关联成本极低:
var revenues = await _context.SaleTransaction .GroupBy(s => s.LocationId) .Select(x => new { LocationId = x.Key, Revenues = x.Sum(i => i.Amount) }) .Join(_context.Locations, stat => stat.LocationId, loc => loc.LocationId, (stat, loc) => new LocationDTO { LocationId = stat.LocationId, LocationName = loc.LocationName, Revenues = stat.Revenues }) .ToListAsync();
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

