Asp.Net Core中如何按关联Episode的TimeSpan属性对Course排序?
错误原因分析
- 第一种写法问题:
OrderByDescending传入的是c.Episodes.Select(...)返回的集合对象,无法作为排序依据,且调用AsEnumerable()会将全量数据加载到内存处理,数据量大时性能极低。 - 第二种写法问题:EF Core 原生不支持直接对
TimeSpan类型执行Sum聚合操作,且代码多写了一个多余的右括号,存在语法错误。
正确实现方案
方案1:数据库端排序(推荐)
直接在SQL层面完成聚合计算和排序,性能最优,写法如下:
// 不需要加载Episode的场景 var sortedCourses = _dbContext.Courses .OrderByDescending(c => c.Episodes.Sum(e => (long?)e.EpisodeTimeLength.Value.Ticks ?? 0)) .ToList(); // 需要关联加载Episode的场景 var sortedCourses = _dbContext.Courses .Include(c => c.Episodes) .OrderByDescending(c => c.Episodes.Sum(e => (long?)e.EpisodeTimeLength.Value.Ticks ?? 0)) .ToList();
逻辑说明:将 TimeSpan 转换为EF支持聚合的 long 类型的Ticks值进行求和,空值默认按0计算,EF可直接将该语句翻译为原生SQL执行。
方案2:内存端排序(仅适合小数据量场景)
如果你的业务场景数据量极小,需要将数据加载到内存后再排序,写法如下:
var sortedCourses = _dbContext.Courses .Include(c => c.Episodes) // 必须加Include加载关联的Episode数据 .AsEnumerable() .OrderByDescending(c => c.Episodes.Sum(e => e.EpisodeTimeLength?.Ticks ?? 0)) .ToList();
注意事项
如果存在没有关联Episode的Course,其总时长默认按0计算,排序时会排在末尾,可根据业务需求调整空值处理逻辑。
内容的提问来源于stack exchange,提问作者Hossein
相关产品推荐
相关产品推荐

