2013-07-20 31 views
1

這個問題在stackoverflow上已經被問了好幾次了,而且我已經閱讀了至少六個這樣的內容,但是我無法繞過簡單的多給很多linq連接查詢。這是我的數據庫EDMX enter image description here如何做Linq多到多加入或不加導航屬性

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

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

因此(無論是C#/ VB.net)查詢像

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

感謝您的任何幫助,其如此簡單的查詢,但我有點卡住

+0

爲什麼你不只是在你的'Student'模型添加另一個屬性,獲取他的主題,以便主題自動加載? – sed

回答

1

一個常規的L​​INQ連接應該做的伎倆。下面是一個簡化的測試案例:

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 
+0

thx爲您的詳細答案,恐怕我得到「名稱ss不在等於左側的範圍」錯誤....:( –

+0

@iAteABug_And_iLiked_it:這個例子應該在一個全新的項目中工作,你正在使用哪個版本的VS和.NET框架?我使用VS 2010 + .NET 4.0在一個全新的控制檯應用程序中進行了測試 – Neolisk

+0

我在VS2012,與.net 4.5 ....也許我做錯了什麼...明天我會花更多的時間,看看我能找出問題。thx –

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

thx ...不幸的是,這隻給了我一個學生名稱以及他們各自的ID名單,它不會獲取主題:( –

+0

@iAteABug_And_iLiked_it奇怪,我只是測試它,併爲我工作的很好 – sed

+0

我'我會在明天花更多的時間在這個項目上,嘗試使用上面的解決方案或者你的解決方案...... thx –

2

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

如果你必須離開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

這是加入冗餘(包括或連接)和幾個db請求之間的折衷,以及請求的複雜性不斷增加。

對於加入節點的「包含」數據是重複的,因此一連串包含可以產生從數據庫到客戶端的巨大流量。
第二種方法的每個級別都要求Where()中的所有較高級別的過濾條件,EF爲第N級別生成N-1個連接的查詢,但沒有冗餘的地方。

據我知道現在EF工作正常載有()和父節點的條件可以用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();