为了账号安全,请及时绑定邮箱和手机立即绑定

关系无法更改,因为一个或多个外键属性是不可空的。

关系无法更改,因为一个或多个外键属性是不可空的。

波斯汪 2019-06-24 15:56:30
关系无法更改,因为一个或多个外键属性是不可空的。当我对一个实体进行GetById()并将子实体的集合设置为来自MVC视图的新列表时,我会得到这个错误。操作失败:由于一个或多个外键属性不可空,关系无法更改。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。我不太明白这句话:关系无法更改,因为一个或多个外键属性是不可空的。为什么我要改变两个实体之间的关系?在整个应用程序的整个生命周期中,它应该保持不变。异常发生的代码是简单地将集合中的修改子类分配给现有的父类。这将有望满足儿童班的取消、新班级的增加和修改的需要。我认为实体框架会处理这个问题。代码行可归纳为:var thisParent = _repo.GetById(1);thisParent.ChildItems = modifiedParent.ChildItems();_repo.Save();
查看完整描述

3 回答

?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

你之所以面临这种情况是因为构图聚集.

在组合中,创建父对象时创建子对象,在其父对象销毁时销毁子对象。..所以它的寿命是由它的父母控制的。博客文章及其评论。如果删除某一帖子,则应删除其评论。对一个不存在的帖子有评论是没有意义的。订单和订单项目相同。

在聚合中,子对象可以存在,而不考虑其父对象。..如果父对象被销毁,子对象仍然可以存在,因为以后可能会添加到其他父对象中。播放列表中的歌曲与播放列表中的歌曲之间的关系。如果播放列表被删除,则不应删除歌曲。它们可以添加到不同的播放列表中。

实体框架区分聚合和组合关系的方式如下:

  • 对于组合:它期望子对象具有一个复合主键(ParentID,child ID)。这是故意的,因为孩子的ID应该在他们的父母的范围之内。

  • 对于聚合:它期望子对象中的外键属性是可空的。

因此,出现此问题的原因是您如何在子表中设置主键。它应该是合成的,但它不是。因此,实体框架将这种关联视为聚合,这意味着,当您删除或清除子对象时,它不会删除子记录。它只需删除关联并将相应的外键列设置为NULL(因此这些子记录以后可以与不同的父记录关联)。由于您的列不允许NULL,所以会得到您提到的异常。

解决办法:

1-如果您有强烈的理由不想使用复合键,则需要显式地删除子对象。这可以比前面提出的解决方案更简单:

context.Children.RemoveRange(parent.Children);

2-否则,通过在子表上设置正确的主键,您的代码将看起来更有意义:

parent.Children.Clear();


查看完整回答
反对 回复 2019-06-24
  • 3 回答
  • 0 关注
  • 1201 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信