2013-06-26 68 views
0

我試圖通過添加適當的包含語句來加速一些我的數據庫層功能,以強制加載並減少我對數據庫進行的查詢次數。無法添加包含(急切加載)到正確的位置

但是,在90%的情況下,我遇到了問題,我並未進入正確的「起始位置」以進入我想要的包含。

我能想出的最簡單的例子:

學生實體,它們之間的許多一對多的關係(以下多個部門的一些課程)。

現在我有一個函數

GetMasterCourses(Department dep)這並不像

return dep.Courses.Where(c => c.level == "Master")

的問題是:我怎麼告訴EF加載與每個相關聯的所有學生詢問課程?

我發現的唯一的解決方案是一樣的東西:

courseIDs = dep.Courses 
    .Where(c => c.level == "Master").Select(c => c.courseID) 
dbcontext.Courses 
    .Include("Students") 
    .Where(c => courseIDs.Contains(c.courseID) and c.level == Master) 

這似乎是愚蠢不得不做這樣的解決辦法,只是爲了能夠指定正確的包含。我已經看過很多Include的例子,並且在stackoverflow上搜索了很多問題,但是不能真正找到任何有這個問題的人,儘管這似乎是一個很常見的問題。

+0

所以你的輸入是一個'部門',是(我假設)不是上下文的一部分。你期望的回報類型是什麼? –

+0

當你加載'Department'時,你是否急於加載'Courses'和'Students'? –

+0

部門是一個函數的參數,例如通過'dbcontext.Departments.First()'檢索。 在此期間,課程和學生確實不急於加載。 期望的返回類型將是IQueryable ,因此一組課程的相關學生收藏急於加載。 – Wannes

回答

1

我看不出爲什麼選擇ID。它看起來像你可以只:

var courses = dep.Courses 
    .Include(i => i.Students) 
    .Where(c => c.level == "Master") 
    .ToList() // or whatever 
+0

'dep.Courses.Include(i => i.Students)'正是我想要做的,但EF不會允許這樣做。看來我只在ObjectQuery對象(即context.Courses)上包含它。我不能像關聯集(dep.Courses)那樣在IQueryable上使用include函數。 我使用的EF 4不是5,但我沒有看到在互聯網上能夠使用包括那樣的一個例子。如果可能的話,請讓我知道。 – Wannes

1

如果您正在使用DbContext(EF> = 4.1):

dbContext.Departments.Attach(dep); 
dep.Courses = dbContext.Entry(dep).Collection(d => d.Courses).Query() 
    .Include(c => c.Students) 
    .Where(c => c.level == "Master") 
    .ToList(); 

如果使用ObjectContextEntityObject派生實體(未波蘇斯):

objectContext.Departments.Attach(dep); 
dep.Courses.Attach(dep.Courses.CreateSourceQuery() 
    .Include("Students") 
    .Where(c => c.level == "Master") 
    .ToList()); 

如果您使用ObjectContext與POCOs it's possible but a bit hairy

以上所有查詢實際上與您的不一樣,因爲您的dep.Courses集合可能不包含數據庫中與部門dep相關的所有課程。 (誰知道你是否在加載後從dep.Courses集合中刪除課程?)在這種情況下,我擔心你的查詢是唯一的方法。

因爲你在談論性能和數據庫的要求優化:如果你想避免的開銷,再次加載課程(你已經在內存中),你也可以嘗試:

courseIDs = dep.Courses 
    .Where(c => c.level == "Master").Select(c => c.courseID); 
var studentDict = dbcontext.Courses 
    .Where(c => courseIDs.Contains(c.courseID)) 
    .Select(c => new 
    { 
     courseID = c.courseID, 
     Students = c.Students 
    }) 
    .ToDictionary(x => x.courseID, x => x.Students); 
foreach (var course in dep.Courses) 
    course.Students = studentDict[course.courseID]; 

它加載少數據,但不一定更高性能,因爲Contains對於大型courseIDs集合具有大量轉換成SQL的成本。