簡體   English   中英

如何進行Linq多對多聯接,無論是否具有導航屬性

[英]How to do Linq Many to Many join with or without navigation properties

這個問題在stackoverflow上已經問過好幾次了,我已經讀了至少六個,但是我無法理解簡單的多對多linq join查詢。 這是我的數據庫EDMX 在此處輸入圖片說明

我只是試圖用學生列表以及每個學生的科目填充WPF數據網格。

現在我知道我們可以簡單地使用導航屬性,而不是進行聯接,但是我一直無法獲得正確的結果

所以(C#/ VB.net)查詢就像

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

謝謝您的任何幫助,它的查詢非常簡單,但我有點卡住了

var listOfStudents = db.Student.Select(x => new { Id = x.Id, Name = x.StudentName, Subjects = x.StudentsSubjects.Select(y => y.Subject) });

如果刪除Id從表中的字段StudentsSubject然后從模型中刪除該表並更新你的模型,EF會自動將這個表有兩種導航性能SubjectsStudentsStudentSubject分別實體。

如果必須保留StudentSubject表架構不變,則可以使用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();

常規的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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM