2017-07-17 90 views
1

我有表老师和表学生,对于'老师'表中的每个记录将在表'学生'有多个记录。这里是我的模型类Linq查询返回选择新语句的所有记录

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; 

我不能够得到学生集合在教师表中每个记录,如何做到这一点?

+0

你得到什么错误? – Maxime

+0

没有收到学生记录在对象中的集合,如果学生表中有两个匹配记录为一个教师记录,则返回2条记录。我期待test.cs应该有{id,text,Students count 2} – PRK

+0

看起来你需要一个“group by”来做你想做的事。 –

回答

2

如果您使用适当的实体框架类定义实现一对多关系,那么您的查询将会简单得多。你甚至不需要使用连接,因为实体框架会为你做到这一点。

看到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); 
} 

实体框架会做学生,并为您的TeacherId教师的加入。

除了简单的linq查询,正确的建模也隐藏了数据库建模的方式。如果您的内部模型发生变化,您的dbContext用户将不必更改其代码。例如,如果您将教师 - 学生关系更改为多对多关系,这意味着教师可能有许多学生,并且学生可能有许多教师,则您的教师类的定义不会更改,因此只要类不会改变,上面的查询就不会改变。

5

如果您需要左连接,请将in ssj替换为in ssj.DefaultIfEmpty()

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

return st; 

此采用的是所谓的一组中加入LINQ - 查询中的每个TT匹配以SS在SSJ集合(即{TT,SS的组})。