的关系无法改变,因为一个或多个外键的属性是不可为空(The relationship could n

2019-08-22 20:44发布

(注:这不是一个重复这个问题,尽管它具有相同的例外)。

我在的地方有一个穷人的交易 ,其中的策略是:

  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 。 我已经试过各种东西而不管是什么,不管我如何努力告诉两个想要删除的背景下,不断抛出此异常。

Answer 1:

@Slauma提供了上述评论这个答案,但问我张贴的答案。

问题是,有效的有一个“错误”在实体框架(微软的东西不再建议您使用)的自跟踪实体模板。 特别是有关这个主题的一篇博客文章可以在这里找到 。

具体来说,问题是Context的ObjectStateManager失控与(附后)实体的同步ChangeTracker.State ,你最终不得不使用对象entity.ChangeTracker.State == ObjectState.Deleted但当context.ObjectStateManager认为状态被设置为EntityState.Unchanged 。 这两个显然是非常不同的。 因此,这有效地修复和去寻找附着在上下文中的任何对象EntityState.Unchanged但向下挖掘更深,还检查每个对象的ChangeTracker.StateObjectState.Deleted解决的事情了。

一个简单的,非常彻底的职能工作,围绕这个问题(这为我们运作良好),可在上下文中的T4模板,通过更换进行#region Handle Initial Entity State用下面的代码块:

#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


文章来源: The relationship could not be changed because one or more of the foreign-key properties is non-nullable