2

我一直在使用實體框架分析器來測試我的數據訪問在一個MVC項目,並已跨越幾個頁面,我做了更多的數據庫查詢比我需要,因爲N + 1問題。使用實體框架導航屬性,而不創建大量的查詢(避免N + 1)

下面是一個簡單的例子來說明我的問題:

var club = this.ActiveClub; // ActiveClub uses code similar to context.Clubs.First() 
var members = club.Members.ToList(); 
return View("MembersWithAddress", members); 

視圖遍歷成員,然後遵循各部件上的navigion屬性也顯示他們的地址。每個地址請求都會產生一個額外的數據庫查詢。

解決這個問題的一種方法是使用Include來確保我需要的額外表格被預先查詢。但是,我似乎只能在直接連接到上下文的俱樂部ObjectSet上做到這一點。在這種情況下,ActiveClub屬性由許多控制器共享,我並不總是希望事先查詢成員和地址表。

我希望能夠使用這樣的:

var members = club.Members.Include("Address").ToList(); 

但是,大家是一個EntityCollection並且不具有在其上包括方法。

有沒有辦法強制成員EntityCollection的負載,並要求EF還加載其地址?或者,以這種方式在實體上使用EntityCollection導航屬性,只是一個非常糟糕的主意;當你從上下文中得到它時,你應該知道你正在加載什麼?

回答

5

如果你的實體從EntityObject繼承嘗試使用這樣的:如果你使用波蘇斯與延遲加載代理

var members = club.Members.CreateSourceQuery() 
          .Include("Address") 
          .ToList(); 

嘗試使用此:

var members = ((EntityCollection<Club>)club.Members).CreateSourceQuery() 
                .Include("Address") 
                .ToList(); 

顯然第二個版本是不是很好,因爲POCO用於消除對EF的依賴,但現在您需要將集合轉換爲EF類。另一個問題是查詢將執行兩次。延遲加載將觸發Members一次訪問該屬性,然後在調用ToList時執行第二個查詢。在運行查詢之前,可以通過turning off lazy loading解決。

當你說ActiveClub是共享的我相信這意味着它是類似的東西是派生的控制器中使用的基本控制器中的屬性。在這種情況下,您仍然可以在不同的控制器中使用不同的代碼來填充該屬性。

+0

謝謝。這非常出色。我還可以做很多事情來減少查詢次數,但這是造成最大影響的一次。 – 2011-05-14 11:48:16