Linq在多个层上排序IEnumerable

时间:2016-04-15 07:35:37

标签: c# entity-framework linq sorting

我正在编写一个简单的测试应用程序,以展示如何对从EF上下文中获取的列表进行排序。

“目标”是获取一个列表,按Student.Name排序,然后按Subject.Name

排序
public class Student
{
    public string Name {get;set;}
    public List<ExamScore> ExamScores{get;set;}
}

public class Subject
{
    public string Name{get;set;}
}

public class ExamScore
{
    public Subject Subject{get;set;}
    public int Score{get;set;}
}

第一级排序很简单:

var list = con.Students
    .Include(e => e.ExamScores
        .Select(s => s.Subjects))
    .OrderBy(x => x.Name) //student.Name
    .ToList();

但是添加下一个级别让我感到困惑。

var list = con.Students
    .Include(e => e.ExamScores
        .Select(s => s.Subjects))
    .OrderBy(x => x.Name) //student.Name
    .ThenBy(y => y.ExamScores.???) //subject name???
    .ToList();

输入

Student{"Jannie", ExamScore{ Subject{"Math"}, 90}}
Student{"Jannie", ExamScore{ Subject{"History"}, 70}}
Student{"Jannie", ExamScore{ Subject{"Science"}, 90}}

Student{"Koos", ExamScore{ Subject{"Xhosa"}, 83}}
Student{"Koos", ExamScore{ Subject{"Afrikaans"}, 74}}
Student{"Koos", ExamScore{ Subject{"English"}, 78}}

Student{"Pieter", ExamScore{ Subject{"Afrikaans"}, 65}}
Student{"Pieter", ExamScore{ Subject{"History"}, 80}}
Student{"Pieter", ExamScore{ Subject{"Math"}, 70}}

Student{"Sannie", ExamScore{ Subject{"Science"}, 60}}
Student{"Sannie", ExamScore{ Subject{"Math"}, 55}}
Student{"Sannie", ExamScore{ Subject{"Biology"}, 75}}

Student{"Magriet", ExamScore{ Subject{"Biology"}, 75}}
Student{"Magriet", ExamScore{ Subject{"English"}, 80}}
Student{"Magriet", ExamScore{ Subject{"Science"}, 90}}

预期输出

Student{"Jannie", ExamScore{ Subject{"History"}, 70}}
Student{"Jannie", ExamScore{ Subject{"Math"}, 90}}
Student{"Jannie", ExamScore{ Subject{"Science"}, 90}}

Student{"Koos", ExamScore{ Subject{"Afrikaans"}, 74}}
Student{"Koos", ExamScore{ Subject{"English"}, 78}}
Student{"Koos", ExamScore{ Subject{"Xhosa"}, 83}}

Student{"Magriet", ExamScore{ Subject{"Biology"}, 75}}
Student{"Magriet", ExamScore{ Subject{"English"}, 80}}
Student{"Magriet", ExamScore{ Subject{"Science"}, 90}}

Student{"Pieter", ExamScore{ Subject{"Afrikaans"}, 65}}
Student{"Pieter", ExamScore{ Subject{"History"}, 80}}
Student{"Pieter", ExamScore{ Subject{"Math"}, 70}}

Student{"Sannie", ExamScore{ Subject{"Biology"}, 75}}
Student{"Sannie", ExamScore{ Subject{"Math"}, 55}}
Student{"Sannie", ExamScore{ Subject{"Science"}, 60}}

2 个答案:

答案 0 :(得分:7)

您需要做的是首先展开Student-&gt;主题关系然后您将能够对两者进行排序:

var list = con.Students.Include(e => e.ExamScores.Select(s => s.Subjects))
    .SelectMany(student => student.ExamScores.Select(score => new { Student = student, Score = score }))
    .OrderBy(x => x.Student.Name)
    .ThenBy(x => x.Score.Subject.Name);

这将产生一个可枚举的匿名对象,其中包含按学生姓名和科目名称排序的学生和分数。

答案 1 :(得分:1)

您可以使用.SelectMany()作为Dmitri建议。这里有一个可编辑的工作实例来说明他的答案(我回答的时候正在研究这个问题,所以我不想浪费它,但他的答案是正确的,我当然也赞成了):< / p>

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    public class Student
    {
        public string Name { get; set; }
        public List<ExamScore> ExamScores { get; set; }
    }

    public class Subject
    {
        public string Name { get; set; }
    }

    public class ExamScore
    {
        public Subject Subject 
        {
            get;
            set;
        }

        public int Score { get; set; }
    }

    static class Program
    {
        static void Main()
        {
            var students = new List<Student>
            {
                new Student
                {
                    Name = "C",
                    ExamScores = new List<ExamScore>
                    {
                        new ExamScore {Subject = new Subject {Name = "Z"}, Score = 1},
                        new ExamScore {Subject = new Subject {Name = "Y"}, Score = 2},
                        new ExamScore {Subject = new Subject {Name = "X"}, Score = 3},
                    }
                },

                new Student
                {
                    Name = "B",
                    ExamScores = new List<ExamScore>
                    {
                        new ExamScore {Subject = new Subject {Name = "Z"}, Score = 4},
                        new ExamScore {Subject = new Subject {Name = "Y"}, Score = 5},
                        new ExamScore {Subject = new Subject {Name = "X"}, Score = 6},
                    }
                },

                new Student
                {
                    Name = "A",
                    ExamScores = new List<ExamScore>
                    {
                        new ExamScore {Subject = new Subject {Name = "Z"}, Score = 7},
                        new ExamScore {Subject = new Subject {Name = "Y"}, Score = 8},
                        new ExamScore {Subject = new Subject {Name = "X"}, Score = 9},
                    }
                }
            };

            var orderedStudents = 
                students.SelectMany(s => s.ExamScores.Select(e => new {Student = s, ExamScore = e}))
                .OrderBy(x => x.Student.Name)
                .ThenBy(x => x.ExamScore.Subject.Name);

            foreach (var item in orderedStudents)
            {
                Console.WriteLine($"{item.Student.Name} {item.ExamScore.Subject.Name} {item.ExamScore.Score}");
            }
        }
    }
}