C# Linq高效按hubId分组无重复键值输出指定格式结果
问题背景
现有如下订单数据:
orders: [ {id: 1, hubId: 1, number:1, IsTrue: true}, {id: 2, hubId: 1, number:2, IsTrue: true}, {id: 3, hubId: 1, number:3, IsTrue: false}, {id: 4, hubId: 2, number:4, IsTrue: true}, {id: 5, hubId: 2, number:5, IsTrue: true}, {id: 6, hubId: 2, number:6, IsTrue: false} ]
需求为编写LINQ查询,按hubId对订单分组,输出如下指定格式的结果:
result: [ { hubId: 1, orders: [ {id: 1, number: 1}, {id: 2, number: 2}, ] }, { hubId: 2, orders: [ {id: 4, number: 4}, {id: 5, number: 5}, ] } ]
当前编写的初始查询无法输出符合格式要求的结果,初始代码如下:
var orders = _ordersRepo.GetQueryable<Order>().AsNoTracking() .Where(o => o.IsTrue) .Select(o => new { hubId = o.hubId, number = o.number, id = o.id }).ToList() .GroupBy(o => o.hubId) return orders;
问题原因
初始代码仅完成了分组操作,未对分组结果做结构投影。GroupBy方法默认返回IGrouping<TKey, TElement>类型的集合,和目标结构要求的包含hubId、orders两个属性的对象格式不匹配;同时初始写法在分组前调用ToList(),会将符合条件的数据全量加载到内存后再做分组,性能较差。
正确实现代码
var result = _ordersRepo.GetQueryable<Order>().AsNoTracking() .Where(o => o.IsTrue) .Select(o => new { o.hubId, o.number, o.id }) .GroupBy(o => o.hubId) .Select(g => new { hubId = g.Key, orders = g.Select(o => new { o.id, o.number }).ToList() }) .ToList(); return result;
实现说明
- 过滤条件
Where(o => o.IsTrue)前置,提前筛除无效数据,减少后续计算的数据量 - 移除分组前的
ToList()调用,让分组、投影操作可以被ORM翻译成SQL在数据库端执行,相比内存分组性能更高 - 分组后通过分组键
g.Key获取当前分组对应的hubId值 - 对组内元素再次做投影,仅保留需要的
id、number字段,输出结构完全匹配需求
内容的提问来源于stack exchange,提问作者Nour Mawla
相关产品推荐
相关产品推荐

