2010-09-08 222 views
12

我正在使用實體框架4與MVC,並需要確保任何引用的實體我想在我的視圖中使用已加載控制器方法返回之前,否則視圖吐出恐懼:實體框架 - 急切加載相關實體

ObjectContext實例已被處置,不能再用於需要連接的操作。

當從上下文直選擇,我可以只使用Include(string)方法迫使其被包括在生成的SQL查詢:

var sellers = context.Sellers.Include("Recommendations.User").ToList(); 

但是,如果我有(例如)一個輔助方法接受一個實體並需要加載所有項目,沒有可用的方法Include

void Test(Seller seller) 
{ 
    // ensure all recommendations and their users are loaded 
} 

蠻力方法是遍歷它們:

foreach (var recommendation in seller.Recommendations) 
    recommendation.User.ToString(); // just force a load 

如果我有100項建議,這將創造幕後的101個SQL查詢。理想情況下,我需要一種方法/方法,只需一次訪問SQL即可加載所有的RecommendationUser對象。

讓我看看錢。

編輯我並不是真的有興趣討論這是一個好還是壞的架構。爲了這個問題,我簡化了我的場景。你可以用EF API來做什麼嗎?

EDIT 2

Ladislav's edit的新方法帶來了希望,但似乎我不太有。

我可以實現我通過該想什麼:

context.Sellers.Include("Recommendations.User").Single(s => s.Id == seller.Id); 

這種方法不使用LoadProperty工作...

context.LoadProperty(seller, "Recommendations.User"); 

...因爲它失敗,出現錯誤...

無法找到指定的導航屬性Recommendations.User。

如果您沒有對上下文的引用,則這兩種方法都不起作用。

+0

雖然這不能回答你的問題(因此我把它作爲評論發佈) - 它確實討論了加載相關實體,因爲它目前在EF6中工作。這也是搜索「實體框架負載相關實體」時在Google中出現的第一個SOF鏈接:http://msdn.microsoft.com/en-us/data/jj574232。所以我想我會分享.. – 2014-05-30 14:12:38

回答

3

我認爲這是你的倉庫的工作,應該在你的情況下公開像GetFullSeller(包含所有屬性加載)和GetSeller(只有基本實體)的方法。

編輯:

有幾種方法如何加載在EF v4的導航性能。(使用include)

  • 延遲加載由ObjectContext.LoadProperty
  • 明確裝載

    • 預先加載(不適用於POCO工作)

    沒有自動加載。

  • +1

    這是否意味着你只能使用直接來自存儲庫的對象?如果你通過WCF收到一個實體,然後想要附加它並在其上填充更多的字段,以便在最終保存之前執行更多轉換,該怎麼辦?無論如何,我不認爲這是一個架構問題。我只想知道API是否支持這一點,如果不支持,爲什麼不。 – 2010-09-08 19:57:52

    0

    不是通過您的實際域對象(EntityObject S)的觀點相反,你可能需要使用您的控制器將它們映射成一個模型對象更好地代表了你的觀點實際上應該顯示。這將減少視圖中所需的邏輯數量,並具有避免在其上下文過期後傳遞EntityObjects的令人愉快的副作用。

    編輯根據您的修改:

    沒有,API沒有辦法採取單一的實體對象,使這是在同一時間,它是裝載它的類型的所有其他實體對象一舉以一種特殊的財產爲懶散。你最好把所有的東西放在首位,使用Include提及,就像你在你的問題中提到的一樣。

    +0

    感謝您的回答。爲了清晰起見,我簡化了案例。我確實使用了「視圖模型」,以至於我的觀點幾乎沒有任何邏輯。我的模型與關係密切相關,我不想在視圖模型中重新創建該層次結構,所以我有一個基礎級視圖模型,它有一些實體枚舉。就我而言,我需要在枚舉中對另一個實體進行解引用。這不是一個真正的體系結構問題,就像API一樣。 – 2010-09-08 20:04:21

    +0

    根據你的編輯;)這不是我想要做的。我有一個賣家。我需要加載所有賣家的建議。在每一項建議中,我都需要加載相應的用戶。我不需要加載任何其他賣家。 – 2010-09-08 20:05:43

    +0

    如果我可以發明這個API,我會說'seller.Load(「Recommendations.User」)',就像我在原始實體集合查詢中所做的那樣(如OP所示)。 – 2010-09-08 20:06:40

    2

    我處於同樣的情況。我認爲使用EF很容易陷入101查詢問題。

    解決方案可以創建Seller類的部分類(由EF生成),並實現返回IQueryable的GetSubclassNameQ以及返回具有預加載的IQueryable的GetSubclassNameQFull。

    public partial class Seller{ 
    
        public IQueryable<Recommendation> GetRecommendationsQ(EntityContainer entitycontainer) { 
        return entitycontainer.Recommendations; 
        }  
    
        public IQueryable<Recommendation> GetRecommendationsQFull(EntityContainer entitycontainer) { 
        return this.GetRecommendationsQ(entitycontainer).Include("Recommendations.User"); 
        } 
    
        public IQueryable<Recommendation> GetRecommendationsQ() { 
        return GetRecommendationsQ(new EntityContainer()); 
        } 
    
        public IQueryable<Recommendation> GetRecommendationsQFull() { 
        return this.GetRecommendationsQ().Include("Recommendations.User"); 
        } 
    
    } 
    
    5

    這是一個老問題,但在EF6可以完成對一個實體加載依賴對象,如this

    context.Entry(seller).Collection(s => s.Recommendations).Query().Include(r => r.User)).Load(); 
    

    這將加載所有Recommendations和給定seller

    及其相關 Users