1

这个问题已经在 stackoverflow 上被问过好几次了,我已经阅读了至少六个,但我无法理解一个简单的多对多 linq 连接查询。这是我的数据库 EDMX在此处输入图像描述

我只是想用学生列表以及每个学生的科目来填充 WPF 数据网格。

现在我知道我们可以简单地使用导航属性,而不是进行连接,但我一直无法得到正确的结果

所以一个(C#/VB.net)查询就像

var listOfStudents= // get a list with all students , along with each student's subjects

谢谢你的帮助,这是一个简单的查询,但我有点卡住了

4

3 回答 3

4
var listOfStudents = db.Student.Select(x => new { Id = x.Id, Name = x.StudentName, Subjects = x.StudentsSubjects.Select(y => y.Subject) });
于 2013-07-20T20:48:44.477 回答
2

如果您Id从表中删除字段,StudentsSubject然后从模型中删除此表并更新您的模型,EF 将自动将此表转换为两个导航属性SubjectsStudentsforStudentSubject实体。

如果您必须保持 StudentsSubject 表架构不变,您可以使用Include()方法来获取学生及其科目:

var students = dbContext.Students.Include("StudentsSubject.Subject")

使用“普通”导航属性,您可以编写以下内容:

var students = dbContext.Students.Include("Subjects")

有时您需要组装大图,然后 Include() 和延迟加载会影响性能。这种情况有一个小技巧:

// switch off for performance
DbContext.Configuration.AutodetectChangesEnabled = false;

// load root entities   
var roots = dbContext.Parents.Where( root => %root_condition%).ToList();

// load entities one level lower
dbContext.DependentEntities.Where( dependent => dependent.Root%root_condition% && %dependent_condition%).ToList();

// detect changes
dbContext.ChangeTracker.DetectChanges();

// enable changes detection.
DbContext.Configuration.AutodetectChangesEnabled = true;

现在root.Dependents集合已填充为roots.

这是连接冗余(包括或连接)和几个数据库请求之间的权衡,以及请求的复杂性增加。

对于连接节点的“包含”数据是重复的,因此包含链可以产生从数据库到客户端的巨大流量。
使用第二种方法,每个级别都需要在 Where() 中过滤所有上层的条件,EF 为第 N 级生成具有 N-1 个连接的查询,但没有冗余的地方。

据我所知,EF 现在可以很好地与 Contains() 一起使用,并且父节点的条件可以替换为Contains()

// load root entities   
var roots = dbContext.Parents.Where( root => %root_condition%).ToList();

var rootIds = new List<int>( roots.Select( root => root.Id));

// load entities one level lower
dbContext.DependentEntities.Where( dependent => %dependent_condition% && rootIds.Contains( dependent.RootId)).ToList();
于 2013-12-12T21:33:29.977 回答
1

常规的 LINQ 连接应该可以解决问题。这是一个简化的测试用例:

Public Class Student
  Public Property Id As String
  Public Property StudentName As String
  Public Property GPA As String
End Class

Public Class StudentsSubject
  Public Property SubjectId As String
  Public Property StudentId As String
  Public Property Id As String
End Class

Public Class Subject
  Public Property Id As String
  Public Property SubjectName As String
End Class

Sub Main()
  Dim students As New List(Of Student)
  students.Add(New Student With {.Id = "1", .GPA = "GPA1", .StudentName = "John"})
  students.Add(New Student With {.Id = "2", .GPA = "GPA2", .StudentName = "Peter"})

  Dim subjects As New List(Of Subject)
  subjects.Add(New Subject With {.Id = "100", .SubjectName = "Maths"})
  subjects.Add(New Subject With {.Id = "200", .SubjectName = "Physics"})

  Dim studentsSubject As New List(Of StudentsSubject)
  studentsSubject.Add(New StudentsSubject With {.Id = "10", .StudentId = "1", .SubjectId = "100"})
  studentsSubject.Add(New StudentsSubject With {.Id = "20", .StudentId = "1", .SubjectId = "200"})
  studentsSubject.Add(New StudentsSubject With {.Id = "30", .StudentId = "2", .SubjectId = "100"})

  Dim listOfStudents = From st In students
                       Join ss In studentsSubject On ss.StudentId Equals st.Id
                       Join sb In subjects On ss.SubjectId Equals sb.Id
                       Select st.StudentName, st.GPA, sb.SubjectName
End Sub
于 2013-07-20T20:25:09.233 回答