的关系无法改变,因为一个或一个以上的外键的属性是不可为空 [英] The relationship could not be changed because one or more of the foreign-key properties is non-nullable

查看:227
本文介绍了的关系无法改变,因为一个或一个以上的外键的属性是不可为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(注意:这是不可以的<一个副本href="http://stackoverflow.com/questions/5538974/the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-pro">this问题即使它具有相同的例外。)

(NOTE: This is not a duplicate of this question even though it has the same exception.)

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

I have a poor man's transaction in place where the strategy is:

  1. 插入一个家长和孩子的记录。
  2. 执行长时间运行的操作。
  3. 如果长时间运行的操作失败,请删除previously插入父母与子女的记录。

当我尝试第3步,我得到以下信息:

When I attempt step 3, I get the following message:

操作失败:关系无法改变,因为一个或一个以上的外键的属性是不可为空。当做出改变有关系,相关的外键属性设置为空值。如果外键不支持空值,一个新的关系必须定义,外键属性必须指定一个非空值,或者不相关的对象必须被删除。

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

我大致明白这是什么意思,但我想我是通过打我怎么努力按规则玩的规则也不管,我不确定为什么我得到这个消息。

I understand generally what this means, but I thought I was playing by the rules and no matter how hard I try to play by the rules, I'm unsure why I'm getting this message.

我们使用的自跟踪实体的,我的code是有效的:

We use self-tracking entities and my code is effectively this:

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

What's wrong with this logic? Why am I not able to simply delete these two records? I've tried calling MyContext.ApplyChanges after I call MarkAsDeleted. I've tried all sorts of things and no matter what, no matter how hard I try to tell the Context that I want both of them deleted, it keeps throwing this exception.

推荐答案

@Slauma 在上面发表了这样的回答但要我张贴的答案。

@Slauma provided this answer in the above comments but asked me to post the answer.

现在的问题是,有有效地为实体框架(微软的东西不再建议使用)的自跟踪实体模板的错误。博客文章专门就这个话题可以是<一个href="http://blog.alner.net/archive/2011/11/01/dont_reuse_context_with_entity_framework_self_tracking_entities.aspx"相对=nofollow>这里找到。

The problem is that there is effectively a "bug" in the Self-Tracking Entities templates for Entity Framework (something Microsoft no longer recommends you use). A blog post specifically on this topic can be found here.

具体而言,问题是,上下文的 ObjectStateManager 失控的(附后)实体的同步 ChangeTracker.State 你最终不得不物体 entity.ChangeTracker.State == ObjectState.Deleted 但是当 context.ObjectStateManager 认为,状态设置为 EntityState.Unchanged 。这两个显然是非常不同的。所以,此修复程序有效地去和查找为 EntityState.Unchanged 附加到上下文中的任何对象,但挖陷的也检查每个对象的 ChangeTracker.State ObjectState.Deleted 来解决的事情了。

Specifically, the problem is that the Context's ObjectStateManager gets out of sync with the (attached) entities' ChangeTracker.State and you end up having objects with entity.ChangeTracker.State == ObjectState.Deleted but when the context.ObjectStateManager thinks that the state is set to EntityState.Unchanged. These two are clearly very different. So this fix effectively goes and looks for any object attached to the context as EntityState.Unchanged but digs down deeper and also checks each object's ChangeTracker.State for ObjectState.Deleted to fix things up.

这是简单的,非常彻底的职能工作,围绕这个问题(这为我们运作良好),可以通过替换#地区处理初始实体状态具有以下code座:

An easy and very thoroughly-functional work-around for this problem (that has worked well for us) can be made in the Context's T4 template by replacing the #region Handle Initial Entity State block with the following code:

#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

这篇关于的关系无法改变,因为一个或一个以上的外键的属性是不可为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆