簡體   English   中英

由於一個或多個外鍵屬性不可為空,因此無法更改該關系

[英]The relationship could not be changed because one or more of the foreign-key properties is non-nullable

(注意:即使有相同的例外,也不能重復此問題 。)

我有一個窮人的交易策略是:

  1. 插入父子記錄。
  2. 執行長時間運行的操作。
  3. 如果長時間運行的操作失敗,請刪除以前插入的父記錄和子記錄。

當我嘗試第3步時,收到以下消息:

操作失敗:由於一個或多個外鍵屬性不可為空,因此無法更改該關系。 對關系進行更改時,相關的外鍵屬性將設置為空值。 如果外鍵不支持空值,則必須定義新的關系,必須為外鍵屬性分配另一個非空值,或者必須刪除不相關的對象。

我通常理解這意味着什么,但是我認為我在遵守規則,無論我多么努力地遵循規則,我不確定為什么會收到此消息。

我們使用自我跟蹤實體,而我的代碼實際上是這樣的:

var parent = new Parent(1,2,3);
var child = new Child(4,5,6);
parent.Children.Add(child);

MyContext.Parents.ApplyChanges(parent);
MyContext.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);

// At this point, inserts were successful and entities are in an Unchanged state.
// Also at this point, I see that parent.Children.Count == 1

var shouldDeleteEntities = false;
try
{
  // This is not database-related. This process does some
  // encryption/decryption and uploads some files up to
  // Azure blob storage. It doesn't touch the DB.
  SomeLongRunningProcess();
}
catch
{
  // Oops, something bad happened. Let's delete the entities!
  shouldDeleteEntities = true;
}

// At this point, both entities are in an Unchanged state, child still
// appears in parent.Children, nothing is wrong that I can see.
parent.MarkAsDeleted();
child.MarkAsDeleted();

// I've tried MyContext.ApplyChanges here for both entities, no change.

// At this point, everything appears to be in the state that
// they're supposed to be!
try
{
  MyContext.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
}
catch
{
  // This exception was thrown and I can't figure out why!
}

這種邏輯有什么問題? 為什么我不能簡單地刪除這兩個記錄? 我在調用MyContext.ApplyChanges之后嘗試調用MarkAsDeleted 我已經試過各種東西而不管是什么,不管我如何努力的告訴下,我想他們刪除,就不斷拋出此異常。

@Slauma在上述評論中提供了此答案,但要求我發布答案。

問題是實體框架的“自我跟蹤實體”模板中實際上存在“錯誤”(Microsoft不再建議您使用此錯誤)。 有關此主題的博客文章可以在這里找到

具體來說,問題是上下文的ObjectStateManager與(附加的)實體的ChangeTracker.State不同步,最終導致對象具有entity.ChangeTracker.State == ObjectState.Deleted但是當context.ObjectStateManager認為狀態為設置為EntityState.Unchanged 這兩個顯然有很大的不同。 因此,此修補程序有效地進行了查找,並以EntityState.Unchanged查找附加到上下文的任何對象,但進行了更深入的挖掘,還檢查了每個對象的ChangeTracker.State中的ObjectState.Deleted以進行修復。

通過使用以下代碼替換#region Handle Initial Entity State塊,可以在Context的T4模板中輕松解決此問題(對我們很有效),並且功能非常全面。

#region Handle Initial Entity State

var existingEntities = context
    .ObjectStateManager
    .GetObjectStateEntries(System.Data.EntityState.Unchanged)
    .Select(x => x.Entity as IObjectWithChangeTracker)
    .Where(x => x != null);

var deletes = entityIndex.AllEntities
                    .Where(x => x.ChangeTracker.State == ObjectState.Deleted)
                    .Union(existingEntities
                            .Where(x => x.ChangeTracker.State == ObjectState.Deleted));

var notDeleted = entityIndex.AllEntities
                    .Where(x => x.ChangeTracker.State != ObjectState.Deleted)
                    .Union(existingEntities
                            .Where(x => x.ChangeTracker.State != ObjectState.Deleted));

foreach (IObjectWithChangeTracker changedEntity in deletes)
{
    HandleDeletedEntity(context, entityIndex, allRelationships, changedEntity);
}

foreach (IObjectWithChangeTracker changedEntity in notDeleted)
{
    HandleEntity(context, entityIndex, allRelationships, changedEntity);
}

#endregion

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM