迁移至.NET Core 2.2后,GroupedEnumerable如何设置OrderBy?结果集未排序
问题根源分析
你遇到的排序完全无效的问题,核心是错误地把字符串拼接结果直接传给了OrderBy的lambda表达式。OrderBy需要的是一个能提取排序键的委托/表达式树,而不是固定字符串——你写的g.OrderBy(g2 => sortBy + " " + sortOrder),本质是把每个元素都映射成同一个固定字符串(比如"setEmployee asc"),所有元素的排序键完全相同,自然不会产生任何排序效果。后面的result.OrderBy(r => sortBy + sortOrder)也是同样的逻辑错误。
修复方案
我们需要根据sortBy参数动态选择要排序的属性,再结合sortOrder决定升序或降序。这里提供两种实用的实现方式:
方式1:Switch-Case映射排序逻辑(简单直接,适合字段少的场景)
针对你的视图列(Date、Id、setEmployee),直接通过switch判断sortBy的值,生成对应的排序规则:
public IEnumerable<EvaluationSummary> GetEvaluationSummaries(string sortBy, string sortOrder, Filter filter = null) { var request = Mapper.MapSearchNominationRequest(filter); request.IsDetailed = false; var response = myService.SearchNominationsAsync(request).GetAwaiter().GetResult(); var groupedSet = response.mySet.GroupBy(n => n.SetId); // 先处理分组内的排序,获取每组的最后一个元素 var result = groupedSet.Select(g => { IOrderedEnumerable<ServiceClients.myClient.NominationObject> sortedGroup; // 统一转小写避免大小写匹配问题 switch(sortBy?.ToLower()) { case "date": sortedGroup = sortOrder?.ToLower() == "desc" ? g.OrderByDescending(x => x.Date) : g.OrderBy(x => x.Date); break; case "id": sortedGroup = sortOrder?.ToLower() == "desc" ? g.OrderByDescending(x => x.Id) : g.OrderBy(x => x.Id); break; case "setemployee": // 注意分组内的对象是NominationObject,对应属性是employee sortedGroup = sortOrder?.ToLower() == "desc" ? g.OrderByDescending(x => x.employee) : g.OrderBy(x => x.employee); break; default: // 默认按日期升序排序 sortedGroup = g.OrderBy(x => x.Date); break; } return Mapper.MapEvaluationSummary(sortedGroup.Last()); }); // 对最终的EvaluationSummary结果集再次排序(根据业务需求选择是否保留) IOrderedEnumerable<EvaluationSummary> sortedResult; switch(sortBy?.ToLower()) { case "date": sortedResult = sortOrder?.ToLower() == "desc" ? result.OrderByDescending(r => r.setDate) : result.OrderBy(r => r.setDate); break; case "id": sortedResult = sortOrder?.ToLower() == "desc" ? result.OrderByDescending(r => r.setId) : result.OrderBy(r => r.setId); break; case "setemployee": sortedResult = sortOrder?.ToLower() == "desc" ? result.OrderByDescending(r => r.setEmployee) : result.OrderBy(r => r.setEmployee); break; default: sortedResult = result.OrderBy(r => r.setDate); break; } return sortedResult; }
方式2:表达式树实现通用动态排序(适合字段多、需要复用的场景)
如果你的实体字段很多,不想写大量switch-case,可以用表达式树动态构建排序委托,实现通用的动态排序:
// 封装通用的动态排序扩展方法 public static IOrderedEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string sortBy, string sortOrder) { var parameter = Expression.Parameter(typeof(T), "x"); // 动态获取属性,注意sortBy必须和实体属性名完全匹配 var property = Expression.Property(parameter, sortBy); // 构建lambda表达式,转换为object类型兼容不同属性类型 var lambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), parameter); return sortOrder?.ToLower() == "desc" ? source.OrderByDescending(lambda.Compile()) : source.OrderBy(lambda.Compile()); } // 在你的业务方法中使用 public IEnumerable<EvaluationSummary> GetEvaluationSummaries(string sortBy, string sortOrder, Filter filter = null) { var request = Mapper.MapSearchNominationRequest(filter); request.IsDetailed = false; var response = myService.SearchNominationsAsync(request).GetAwaiter().GetResult(); var groupedSet = response.mySet.GroupBy(n => n.SetId); // 分组内排序时,注意视图传的sortBy和NominationObject属性的映射 var groupSortBy = sortBy?.ToLower() == "setemployee" ? "employee" : sortBy; var result = groupedSet.Select(g => { var sortedGroup = g.OrderByDynamic(groupSortBy, sortOrder); return Mapper.MapEvaluationSummary(sortedGroup.Last()); }); // 对结果集执行动态排序 var sortedResult = result.OrderByDynamic(sortBy, sortOrder); return sortedResult; }
额外修复点
你的MapEvaluationSummary方法缺少返回语句,会导致编译错误,记得补上:
public EvaluationSummary MapEvaluationSummary(SetObject setIn) { var eval = new EvaluationSummary { setDate = setIn.Date, setId = setIn.Id, setTypeId = setIn.TypeId, setTypeDescription = setIn.TypeDescription, setStatusId = setIn.StatusId, setStatusDescription = setIn.StatusDescription, setBy = setIn.Manager, setEmployee = setIn.employee }; return eval; // 必须添加返回语句 }
内容的提问来源于stack exchange,提问作者Hayen
相关产品推荐
相关产品推荐

