Dot-Net

成員“X”被更改為與協會成員“Y”不一致

  • May 15, 2013

如果我按照以下步驟操作,我會收到此錯誤:

  1. 更改對象的屬性 Y(關聯的實體屬性)
  2. 嘗試送出更改
  3. 此時 Y 的值和 X(基礎鍵)的值不一致——LINQ to SQL 顯然在呼叫 GetChangeSet 之前不會同步這些。
  4. 在更新操作期間,由於某些業務邏輯或數據庫級別的約束而發生預期錯誤。
  5. 此時 Y 的值與 X 一致,因為呼叫了 GetChangeSet。
  6. 將 Y 的值更改為 Nothing(也稱為 null)。
  7. 呼叫 GetChangeSet。

錯誤出現在最後一步是因為X的值和X的原始值(由GetOriginalEntityState返回)不同,新的值和Y不一致?這是為什麼?這是 LINQ to SQL 中的錯誤。一定是因為如果我在步驟 5 中將 Y 更改為另一個(非空)值,我看不到相同的行為。解決這個問題的正確方法是什麼?我可以看到幾種方法:

  1. 發生錯誤時丟棄 DataContext 並保持 UI 不變。我不喜歡這樣,因為這樣就無法檢測到樂觀的並發更改衝突。新上下文中沒有在填充 UI 的同時填充的原始值,因此如果 UI 中有任何過時的值,它們將導致數據庫中的數據恢復。
  2. 刷新數據上下文 (OverwriteCurrent) 並保持 UI 不變。我不喜歡這個,原因與#1 相同。
  3. 刷新數據上下文 (OverwriteCurrent) 並重新填充 UI。我不喜歡這樣,因為剛剛呈現給使用者的錯誤消息不會向使用者顯示他們犯的錯誤並允許他們更正它。它還會丟棄使用者可能進行的所有其他更改。
  4. 當錯誤發生時,顯式檢索與X原始值對應的Y鍵並重置Y,然後呼叫GetChangeSet重新同步X(X是只讀的或私有的,所以我不能直接重置它)。這似乎可行,但似乎是一種 hack,並且可能需要大量程式碼來解決其他類似錯誤。

有沒有更好的解決方案。這是應該報告的事情嗎?

看起來此錯誤已在最新的 .NET 和/或 Visual Studio 2010 中修復。為 DBML 文件生成的程式碼現在包含更新基礎外鍵值的程式碼,即使將關聯屬性設置為 null:

   [global::System.Data.Linq.Mapping.AssociationAttribute(Name="Customer_Order", Storage="_Customer", ThisKey="fkCustomer", OtherKey="id", IsForeignKey=true)]
   public Customer Customer
   {
       get
       {
           return this._Customer.Entity;
       }
       set
       {
           Customer previousValue = this._Customer.Entity;
           if (((previousValue != value) 
                       || (this._Customer.HasLoadedOrAssignedValue == false)))
           {
               this.SendPropertyChanging();
               if ((previousValue != null))
               {
                   this._Customer.Entity = null;
                   previousValue.Orders.Remove(this);
               }
               this._Customer.Entity = value;
               if ((value != null))
               {
                   value.Orders.Add(this);
                   this._fkCustomer = value.id;
               }
               else
               {
                   this._fkCustomer = default(Nullable<int>);
               }
               this.SendPropertyChanged("Customer");
           }
       }
   }

我認為this._fkCustomer = default(Nullable<int>);當我最初發布這個問題時,我正在測試的程式碼中一定不存在。所以要麼我的 DBML 設置錯誤,要麼這個問題得到了解決。

對於 MSDN:

對於關係的更新,從子代到父代的引用(即外鍵對應的引用)被認為是權威。反向(即從父級到子級)的引用是可選的。關係類(EntitySet 和 EntityRef)保證雙向引用對於一對多和一對一關係是一致的。如果對像模型不使用 EntitySet 或 EntityRef,並且如果存在反向引用,則您有責任在更新關係時使其與正向引用保持一致。

如果您同時更新所需的引用和相應的外鍵,則必須確保它們一致。如果在呼叫 SubmitChanges 時兩者不同步,則會引發 InvalidOperationException 異常。儘管外鍵值更改足以影響基礎行的更新,但您應該更改引用以保持對像圖的連通性和關係的雙向一致性。

<http://msdn.microsoft.com/en-us/library/Bb386982(v=VS.90).aspx>

引用自:https://stackoverflow.com/questions/4588294