2014-01-27 53 views
0

我們遇到實體框架返回的值爲非空可關聯的NULL值。我們首先工作模型。 當一個實體的關係在不同的上下文中(或者在我們真實的用例中:一個不同的線程)發生了變化時,就會出現這個問題。
- 如果導航屬性還沒有被調用,它將返回null。
- 如果導航屬性HAS在OR中包含實體中的外鍵屬性之前被調用,它將返回最後一個已知值。實體框架中的不可爲空導航屬性爲空

enter image description here

  • 延遲加載爲
  • 我已經測試此爲實體框架4.0和6.0,他們都產生相同的結果

這是一個例子模型模型啓用

這是一些演示問題的示例測試代碼。

int ID; 
using (Model1Container1 context = new Model1Container1()) 
{ 
    Dossier d = new Dossier(); 
    d.Fase = new Fase(); 
    context.DossierSet.AddObject(d);//generate new object with relationship 
    context.SaveChanges(); 
    ID = d.Id; 
} 
using (Model1Container1 context = new Model1Container1()) 
{ 
    Dossier storedDossier = context.DossierSet.Single(x => x.Id == ID);//retrieve the saved entity 
    using (Model1Container1 context2 = new Model1Container1()) 
    { 
     Dossier faseDossier = context2.DossierSet.Single(x => x.Id == ID);//modify the saved entity in a different context 
     faseDossier.Fase = new Fase(); 
     context2.SaveChanges(); 
    } 
    Console.WriteLine(storedDossier.Fase.Id);//attempt to read the changed property. NULL exception here on storedDossier.Fase 
} 

該代碼並不在我們的現實情況下使用線程一樣,但它描述了同樣的問題。在實際的應用程序中,可以在不同的PC上使用完全不同的應用程序來修改數據庫中的實體。

這裏的問題是,爲什麼會發生這種行爲?這可能是實體框架中的錯誤嗎?

我們很清楚,實體框架無法檢索當實體由於延遲加載而實例化時存在的關係,但爲什麼它不會加載更改後的關係呢?突然收到NULL值不爲空的實體是意想不到的東西,我們還沒有在我們的代碼都認爲(和我們爲什麼要擺在首位?)

+0

發生這種情況是因爲每個上下文意味着不同的事務您應該調用它們嵌套在TransactionScope中。 – Fals

+0

Fals:我們的實體被延遲加載,這意味着該屬性可以隨時在程序中調用,遠遠超過從數據庫中檢索實體。與此同時,數據庫的值可能已經被另一個上下文實例改變了(就像在一個線程中一樣)。 – Olaf

+1

延遲加載與您的問題無關。您正在調用兩個不同的上下文來更新尚未提交的內容。這是問題。你必須像這樣使用TransactionScope:http://msdn.microsoft.com/en-us/data/dn456843 – Fals

回答

0

更換

context.DossierSet.Single(x => x.Id == ID); 

context.DossierSet.Include(x => x.Fase).Single(x => x.Id == ID); 
+1

這適用於這個示例,但這意味着您必須在*每個*點處包含此代碼,以便在應用程序中調用實體,因爲它具有*每個*關係。它沒有解決或爲這個問題的核心提供不同的方法:每個不可空的實體都有可能爲空 – Olaf