1

這是我第一篇文章,所以我希望一切都很好。EF STE和自參考表問題

這裏是我的問題: 我有一個表在我的數據庫稱爲UserTypes。它有:

  1. ID;
  2. IsPrivate;
  3. Parent_ID;

有關的是第一個和第三個。 我有另一個表叫UserTypes_T其中有不同類型的信息,即語言特定。這些字段是:

  1. Language_ID;
  2. UserType_ID;
  3. 名稱;

我試圖做到的,是從UserTypes表加載整個層次結構,並顯示在一個TreeView(這是不相關的現在)。然後,通過選擇一些用戶類型,我可以在單獨的編輯框(名稱)和組合框(父)中編輯它們。

一切工作正常,直到我試圖堅持數據庫中的更改。 EF爲我生成兩個實體類爲這些表:

用戶類型的類有:

  1. ID;
  2. IsPrivate;
  3. Parent_ID;
  4. 自引用的導航屬性(0..1);
  5. 子元素的導航屬性;
  6. UserTypes_T表的另一個導航屬性(1 .. *);

用於翻譯的信息的類有:

  1. UserType_ID;
  2. Language_ID;
  3. 名稱;
  4. UserTypes表的導航屬性(* .. 1);
  5. 語言表的導航屬性(* .. 1);

我得到我需要使用數據:

return context.UserTypes.Include("UserTypes_T").Where(ut => ut.IsPrivate==false).ToList(); 

在我的WCF Web服務。我可以添加沒有問題的新用戶類型,但是當我嘗試更新舊用戶時,會發生一些奇怪的事情。

如果我更新根元素(Parent_ID == null),一切正常! 如果我更新的元素,其中PARENT_ID = NULL我收到以下錯誤:我找遍了互聯網

AcceptChanges cannot continue because the object’s key values conflict with another object in the ObjectStateManager.

Diego B Vega(還有更多)閱讀博客文章,但我的問題是不同的。當我更改父級用戶類型時,實際上我更改了Parent_ID屬性,而不是導航屬性。我總是嘗試使用ID而不是生成的導航屬性來避免問題。

我做了一個小調查,想看看什麼是對象圖,我得到,看到,有很多重複的實體:

根元素有它的子元素的列表。每個子元素都具有對根或其父代的反向引用等等。你可以想象。由於我沒有使用這些導航屬性,因爲我使用ID來獲取/設置我需要的數據,所以我將它們從模型中刪除。具體我刪除了點和 用戶類型實體類。然後我有一個對象圖,每個元素只有一次。我嘗試了一個新的更新,但我有同樣的問題:

根元素更新正常,但有一些父母的元素拋出了相同的異常。

我看到我在UserTypes_T實體類中有一個導航屬性,指向一個用戶類型,所以我也刪除了它。然後這個錯誤消失了。對象圖中的所有項目都是唯一的。但問題仍然是 - 我可以毫無問題更新我的根元素,但是當試圖更新子(無例外),我在生成Model.Context.Extensions類空引用異常:

if (!context.ObjectStateManager.TryGetObjectStateEntry(entityInSet.Item2, out entry)) 
{ 
    context.AddObject(entityInSet.Item1, entityInSet.Item2);//here! 
} 

我試圖只更新名稱(這在UserTypes_T),但錯誤是相同的。

我出來的想法,我一直試圖解決這個問題現在8個小時,所以我會很感激,如果有人給我的想法或分享他們的經驗。

PS:

我成功更新子對象是使用下面的代碼來獲取數據的唯一方法:

var userTypes = argoContext.UserTypes.Include("UserTypes_T").Where(ut => ut.IsPrivate==false).ToList(); 
foreach (UserType ut in userTypes) 
{ 
    ut.UserType1 = null; 
    ut.UserTypes1 = null; 
} 
return userTypes; 

其中UserType1是導航性能,指向父用戶類型和UserTypes1是導航屬性,其中包含子元素的列表。這裏的問題是EF「修正」了對象並將Parent_ID更改爲null。如果我再次設置它,EF也會設置UserTypes1 ...也許有一種方法可以阻止此行爲?

回答

1

確定大家,我剛剛發現問題所在,如果有其他人遇到相同問題,我會發布答案。

問題是,我正在服務器上進行一些驗證,以查看用戶類型之間是否沒有循環引用。所以,我在服務器上的方法看起來是這樣的:

using (MyEntities context = new MyEntities()) 
{ 
    string errMsg = MyValidator.ValidateSomething(context.UserTypes,...); 
    if (!string.IsNullOrEmpty(errMsg)) throw new FaultException(errMsg); 
    //some other code here... 
    context.UserTypes.ApplyChanges(_userType);//_userType is the one that is updated 
    context.UserTypes.SaveChanges(); 
} 

的問題是,使驗證時,背景填充,並試圖保存更改時,也有使用相同的密鑰值的對象。

解決方法很簡單 - 使用不同背景服務器上驗證的事情:

using (MyEntities validationContext = new MyEntities()) 
{ 
    //validation goes here... 
} 
using (MyEntities context = new MyEntities()) 
{ 
    //saving changes and other processing... 
} 

另外一個可能是:

using (MyEntities context = new MyEntities()) 
{ 
    using (MyEntities validationContext = new MyEntities()) 
    { 
     //validation 
    } 
    //saving changes and other processing... 
} 

這就是它!我希望對別人有用!