LINQ OrderBy ThenByDescending 使用 C# 中两个表中的数据

LINQ OrderBy ThenByDescending using data from two tables in C#

我有一个 table Student 包含这些列:

ID (PK, bigint, not null)
Height (int, not null)
IQ (int, not null)
SchoolId (bigint, not null)

和一个 table School 列:

ID (PK, bigint, not null)
Charter (bit, not null)   -- 1 means charter, 0 means not charter

我也有方法

private static IEnumerable<IStudent> SortStudentList(IEnumerable<IStudent> students)
{
    return students.OrderBy(s => s.Height).ThenBy(s => s.IQ);
}

这很好用。但是现在,我还需要按宪章排序。在英语中,“按身高升序排序,然后按 Charter 降序排序(首先获得 Charter schools),然后按 IQ 升序排序”

类似于:

private static IEnumerable<IStudent> SortStudentList(IEnumerable<IStudent> students)
{
    return students.OrderBy(s => s.Height).ThenByDescending(s => s.GetCharterStatus).ThenBy(s => s.IQ);
}

实体(我正在使用 Entity Framework)Student 确实有一个 link 到 School 通过

public class Student, IStudent
{
     ...
      [Index(IsUnique = true)]
      public long SchoolId { get; set; }
     ...
}

public interface IStudent
{
      ...
      long SchoolId {get;set;}
      ...
 }

奇怪的是,当我使用 SQLite/SQL Server Compact Toolbox 查看关系时,我没有看到 SchoolId 列表作为外键,而是在 Student table 的“Indexes”文件夹下它显示为

IX_SchoolId (Unique)

我在弄清楚如何获取查询的特许学校部分时遇到问题,并且尝试了各种方法。我需要以某种方式加入吗?

如果我可以澄清或提供更多信息,请告诉我。我正在使用 SQL Server CE 和 Entity Framework 尽管我怀疑这与问题无关。

谢谢, 戴夫

P.S。数据是为了保护公司机密而编造的,但关系是一样的。我对身高、智商和特许学校地位之间的关系没有任何看法:)

I'm having trouble figuring out how to get the Charter school part of the query and have tried various things. Do I need to somehow do a join?

是的,但是有几种方法可以执行此操作,具体取决于您是否使用 ORM。

基于SQL的方法

如果使用普通 SQL,您将需要连接两个表以提取所需的所有数据。查询可能看起来像这样:

SELECT 
    Students.*,
    Schools.Charter           
FROM 
    Students
INNER JOIN 
    Schools ON Students.SchoolId = Schools.Id

这将是 return 一组学生及其“特许学校名称”,可能如下所示:

public class StudentWithSchoolType
{
     // Properties from Student
     public int ID { get; set; }
     public int Height { get; set; }
     public int IQ { get; set; }
     // Properties from Schools
     public bool Charter { get; set; }
}
 

或者,如果您已经在 IStudent 的界面上拥有这些属性,它可能看起来更像:

public class StudentWithSchoolType : IStudent
{
     // Student Properties inherited from IStudent

     public bool Charter { get; set; }
}

如果您将始终执行此操作,您也可以将其包含在界面中,但您的需求可能会有所不同。

获得该数据后,您可以简单地访问需要独立订购的学生或学校数据,因为必要的字段应该是

private static IEnumerable<IStudent> SortStudentList(IEnumerable<IStudent> students)
{
    return students.OrderBy(s => s.Height)
                   .ThenByDescending(s => s.Charter)
                   .ThenBy(s => s.IQ);   
}

基于 ORM 的方法

如果您正在使用像 Entity Framework 这样的 ORM 并且在这两个表之间有关系(即学生 属性 上的学校),那么您可以通过 Include() 从数据库中提取时调用的方法:

// This will populate the School property of the Student with any 
// properties it has
var students = YourContext.Students
                          .Include("School")
                          .ToList();

这将简化您的查询,因为您随后可以使用:

private static IEnumerable<IStudent> SortStudentList(IEnumerable<IStudent> students)
{
    // Notice the use of s.School.Charter
    return students.OrderBy(s => s.Height)
                   .ThenByDescending(s => s.School.Charter)
                   .ThenBy(s => s.IQ);   
}

如果您还没有 School 对象,但有密钥,那么您只需要按如下方式将一个添加到您的 Student 实体中:

public class Student
{
    // Your Student properties here

    [Index(IsUnique = true)]
    [ForeignKey("School")]
    public long SchoolId { get; set; }
    
    public virtual School School  { get; set; }
}

另一种方式,通过添加扩展方法:

public static short GetCharterStatus(this IStudent student, )
{
   return schools.First(school=> school.ID == student.SchoolId).Charter;
}