我有表老师和表学生,表“老师”中的每条记录在表“学生”中都有多条记录。这是我的模特班

public class Test
{
    public int Id { get; set; }
    public string Text { get; set; }
    public List<StudentsDTO> Students{ get; set; }
}


这是我的LINQ查询试图获取记录

     var st = (from tt in context.Teachers
                                    join ss in context.Students
                                    on tt.ID equals ss.teacherID
                                    where tt.TypeID == 2
                                    select new Test
                                    {
                                        Id = tt.ID,
                                        Text = tt.Text,
                                        Students= new List<StudentsDTO>()
                                        {
                                            new StudentsDTO()
                                            {
                                                Name= ss.Name,
                                                Id= ss.StudentID
                                            }
                                        }.ToList()
                                    }).ToList();
            return st;


无法在教师表中为每条记录收集学生,该怎么办?

最佳答案

如果您为一对多关系使用了正确的实体框架类定义,则查询将更加简单。您甚至不必使用联接,因为Entity Framework会为您执行此操作。

Entity Framework Configure One-to-Many Relationship

如果一个老师有零个或多个学生,而每个学生恰好有一个老师,则一对多建模如下:

class Teacher
{
    public int Id {get; set;}

    // a Teacher has zero or more Students:
    public virtual ICollection<Student> Students {get; set;}
    ...
}

class Student
{
    public int Id {get; set;}

    // a Student has exactly one Teacher, via foreign key TeacherId
    public int TeacherId {get; set;}
    public virtual Teacher Teacher {get; set;}
    ...
}

class MyDbContext : DbContext
{
    public DbSet<Teacher> Teachers {get; set;}
    public DbSet<Student> Students {get; set;}
}


因为使用了正确的Code First Conventions,所以这是对教师与学生之间的一对多关系进行建模所需要的。


  在实体框架中,表的列由非虚拟属性表示。虚拟属性表示表之间的关系(一对多,多对多,...)


如果要使用不同的表名或列名,则必须使用属性或流利的API,但ID仍保持不变:教师对其拥有的许多学生拥有ICollection,而学生则具有外键和它拥有的一位老师的财产。

正确定义模型可以使查询更加简单直观:

var result = myDbContext.Teachers                // from the set of Teachers
    .Where(teacher => teacher.TypeId == 2)       // take all teachers with TypeId 2
    .Select(teacher => new Test                  // from every remaining Teacher,
    {                                            // create one Test object
        Id = teacher.Id,                         // With Id is Teach Id
        Text = teacher.Text,                     // Text is teacher.Text
        Students = teacher.Students
            .Select(student => new StudentDTO    // from every Student of this Teacher
            {                                    // create a StudentDTO object
                Id = student.ID,                 // with Id = student.Id
                Name= student.Name,              // Name is student.Name
            })
            .ToList(),                           // create a list of these StudentDTOs
     })
     .ToList();                                  // create a list of all Test objects


我的经验是,由于我对所有实体框架类都进行了正确建模,因此我几乎不必再创建联接。我通常认为是集合而不是联接表。实体框架将知道必须执行哪个(组)联接。

例如:如果您希望使用特定的TeacherCode的老师的所有学生的姓名:

IEnumerable<Student> GetStudentsOfTeacher(string teacherCode)
{
    return myDbContext.Students
       .Where(student => student.Teacher.TeacherCode == teacherCode);
}


实体框架将为您完成Student和Teachers on TeacherId的加入。


  如果要进行组联接(一个包含所有子项的项目,一个包含所有学生的教师的项目),请从一侧开始。如果要进行平口聚会(一位学生和一位老师),请从多方面开始。


除了更简单的linq查询外,正确的建模还隐藏了数据库建模的方式。如果内部模型发生更改,则dbContext的用户无需更改其代码。

例如,如果您将“师生”关系更改为“多对多”关系,这意味着“老师”可能有很多学生,而“学生”可能有很多老师,则您的“老师”类的定义不会更改,因此上面的查询会赢只要班级不变,就不必改变。

关于c# - Linq查询以选择新语句返回所有记录,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45154987/

10-12 15:36
查看更多