这是Jon Skeet已经回答的问题的扩展,你可以find here.
所需的结果如下:
A 100
A 80
B 80
B 50
B 40
C 70
C 30
考虑到你有以下课程:
public class Student
{
public string Name { get; set; }
public int Grade { get; set; }
}
获得结果(在理想情况下)可以使用Jon Skeet的答案来完成:
var query = grades.GroupBy(student => student.Name)
.Select(group =>
new { Name = group.Key,
Students = group.OrderByDescending(x => x.Grade) })
.OrderBy(group => group.Students.FirstOrDefault().Grade);
但是在我的情况下,我还必须在查询中支持分页。这意味着执行 SelectMany(),然后执行跳过()和执行()。但要做 Skip(),您必须应用 OrderBy()。这是我的订单再次破坏的地方,因为我需要保留我在 SelectMany()之后获得的订单。
如何实现这一目标?
var query = grades.GroupBy(student => student.Name)
.Select(group =>
new { Name = group.Key,
Students = group.OrderByDescending(x => x.Grade) })
.OrderBy(group => group.Students.FirstOrDefault().Grade).SelectMany(s => s.Students).OrderBy(something magical that doesn't break ordering).Skip(s => skip).Take(t => take);
我知道我可以在我的查询具体化时再次手动排序记录,但我想避免这种情况,并在从LINQ翻译的一个SQL查询中完成所有这些操作。
答案 0 :(得分:2)
您可以使用Max
采用其他方法,而不是对每个组进行排序并获取第一个值。之后,您可以按最高等级,姓名(如果两名学生具有相同的最高成绩)和成绩订购:
var query = c.Customers
.GroupBy(s => s.Name, (k, g) => g
.Select(s => new { MaxGrade = g.Max(s2 => s2.Grade), Student = s }))
.SelectMany(s => s)
.OrderBy(s => s.MaxGrade)
.ThenBy(s => s.Student.Name)
.ThenByDescending(s => s.Student.Grade)
.Select(s => s.Student)
.Skip(toSkip)
.Take(toTake)
.ToList();
EF6支持所有这些方法,因此您应该得到所需的结果。
答案 1 :(得分:0)
只需重新索引列表结果并在返回之前删除索引。
var query = grades.GroupBy(student => student.Name)
.Select(group =>
new { Name = group.Key,
Students = group.OrderByDescending(x => x.Grade)
})
.OrderBy(group => group.Students.FirstOrDefault().Grade)
.SelectMany(s => s.Students)
.Select((obj,index) => new {obj,index})
.OrderBy(newindex => newindex.index)
.Skip(s => skip).Take(t => take)
.Select(final=> final.obj);