PRK*_*PRK 1 .net c# linq lambda entity-framework
我有表老师和表学生,对于表'老师'中的每个记录,表'学生'中将有多个记录.这是我的模特课
public class Test
{
public int Id { get; set; }
public string Text { get; set; }
public List<StudentsDTO> Students{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是我的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;
Run Code Online (Sandbox Code Playgroud)
我无法为教师表中的每条记录收集学生,该怎么办?
如果你需要一个左连接,更换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;
Run Code Online (Sandbox Code Playgroud)
这在LINQ中使用所谓的组连接 - 查询将每个tt与ssj中的ss集合(即{tt,group of ss})进行匹配.
如果您对一对多关系使用了正确的实体框架类定义,那么您的查询将更加简单.您甚至不必使用连接,因为实体框架会为您执行此操作.
请参阅实体框架配置一对多关系
如果一位教师拥有零个或多个学生,并且每个学生只有一位教师,则一对多的建模如下:
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;}
}
Run Code Online (Sandbox Code Playgroud)
因为使用了正确的代码优先约定,所以只需要模拟教师和学生之间的一对多关系.
在实体框架中,表的列由非虚拟属性表示.虚拟属性表示表之间的关系(一对多,多对多,......)
如果您需要不同的表名或列名,则必须使用属性或流畅的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
Run Code Online (Sandbox Code Playgroud)
我的经验是,因为我正确地模拟了所有的Entity Framework类,所以我很少再创建Joins了.我通常认为在集合中而不是连接表.实体框架将知道必须执行哪个(组)连接.
例如:如果您希望教师的所有学生的姓名具有某个TeacherCode:
IEnumerable<Student> GetStudentsOfTeacher(string teacherCode)
{
return myDbContext.Students
.Where(student => student.Teacher.TeacherCode == teacherCode);
}
Run Code Online (Sandbox Code Playgroud)
实体框架将为您在TeacherId上加入学生和教师.
如果你想进行分组加入(一个包含所有子项目的项目,一个包含所有学生的教师),请从单侧开始.如果你想做一个平坦的加入(这个老师的学生)从多方开始.
除了更简单的linq查询之外,正确的建模还隐藏了数据库建模的方式.如果内部模型发生更改,dbContext的用户将无需更改其代码.
例如,如果您将教师 - 学生关系更改为多对多关系,意味着教师可能有许多学生,而学生可能有许多教师,则不会更改教师课程的定义,因此上面的查询获胜只要课程不会改变,就必须改变.
| 归档时间: |
|
| 查看次数: |
4882 次 |
| 最近记录: |