由于一个或多个外键属性不可为空,因此无法更改该关系

2024-02-09

使用 EF 更新期间出现以下错误:

操作失败:无法更改关系,因为一个或多个外键属性不可为空。当关系发生更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

有没有general如何找到哪些外键属性导致上述错误?

[Update]

对于以下代码导致上述错误的一种情况(我在断开连接的环境中工作,所以我使用graphdiff更新我的对象图),当它想要运行时_uow.Commit();:

public void CopyTechnicalInfos(int sourceOrderItemId, List<int> targetOrderItemIds)
{
  _uow = new MyDbContext();
   var sourceOrderItem = _uow.OrderItems
          .Include(x => x.NominalBoms)
          .Include("NominalRoutings.NominalSizeTests")
          .AsNoTracking()
          .FirstOrDefault(x => x.Id == sourceOrderItemId);


   var criteria = PredicateBuilder.False<OrderItem>();
   foreach (var targetOrderItemId in orderItemIds)
   {
      int id = targetOrderItemId;
      criteria = criteria.OR(x => x.Id == id);
   }
   var targetOrderItems = _uow.OrderItems
                              .AsNoTracking()
                              .AsExpandable()   
                              .Where(criteria)
                              .ToList();

  foreach (var targetOrderItem in targetOrderItems)
  {
        //delete old datas and insert new datas 
        targetOrderItem.NominalBoms = sourceOrderItem.NominalBoms;
        targetOrderItem.NominalBoms.ForEach(x => x.Id = 0);

        targetOrderItem.NominalRoutings = sourceOrderItem.NominalRoutings;
        targetOrderItem.NominalRoutings.ForEach(x => x.Id = 0);
        targetOrderItem.NominalRoutings
                       .ForEach(x => x.NominalTests.ForEach(y => y.Id = 0));
        targetOrderItem.NominalRoutings
                       .ForEach(x => x.NominalSizeTests.ForEach(y => y.Id = 0));
       _uow.OrderItems.UpdateGraph(targetOrderItem, 
                                   x => x.OwnedCollection(y => y.NominalBoms)
                                         .OwnedCollection(y => y.NominalRoutings, 
                                          with => with
                                         .OwnedCollection(t => t.NominalTests)));
   }
   _uow.Commit();
}

在实体框架中,您可以使用外键关联。也就是说,另一个对象的外键表示为两个属性对:原始外键属性(例如NominalRouting.OrderItemId)和对象引用(NominalRouting.OrderItem).

这意味着您可以设置原始值或对象引用来建立外键关联。如果您设置其中一项,EF 会在可能的情况下尝试使另一项保持同步。不幸的是,这也可能会引起原始外键值与其随附引用之间的冲突。

很难说清楚你的情况到底发生了什么。但是,我do知道您将对象从一个父级“复制”到另一个父级的方法......并不理想。首先,更改主键值从来都不是一个好主意。通过将它们设置为0你让物体看起来像新的一样,但它们却不是。其次,您多次将相同的子对象分配给其他父对象。我think结果,您最终会得到大量具有外键的对象value但不是参考.

我说“复制”,因为这就是你似乎想要实现的目标。如果是这样,您应该正确克隆对象并Add他们对每个targetOrderItem。同时,我想知道为什么你(显然)克隆所有这些对象。看起来多对多关联在这里更合适。但那是另一个话题了。

现在你的实际问题是:如何找到冲突的关联?

这非常非常困难。它将需要代码来搜索概念模型并查找外键关联中涉及的属性。然后你必须找到他们的价值观并找到不匹配的地方。足够困难,但与确定何时possible冲突是一个actual冲突。让我通过两个例子来澄清这一点。这里,一堂课OrderItem具有由属性组成的所需外键关联Order and OrderId.

var item = new OrderItem { OrderId = 1, ... };
db.OrderItems.Add(item);
db.SaveChanges();

所以有一个项目OrderId分配和Order= null,EF 很高兴。

var item = db.OrderItems.Include(x => x.Order).Find(10);
// returns an OrderItem with OrderId = 1
item.Order = null;
db.SaveChanges();

再次,一个项目OrderId分配和Order= null,但 EF 抛出异常“关系无法更改...”。

(而且可能发生冲突的情况也比较多)

所以仅仅寻找不匹配的值是不够的OrderId/Order对,您还必须检查实体状态并确切地知道哪些状态组合不允许不匹配。我的建议:忘记它,修复你的代码。

不过,还有一个肮脏的伎俩。当 EF 尝试匹配外键值和引用时,在嵌套树深处的某个位置if它将我们正在讨论的冲突收集到一个成员变量中ObjectStateManager, named _entriesWithConceptualNulls。可以通过一些反射来获得它的值:

#if DEBUG

db.ChangeTracker.DetectChanges(); // Force EF to match associations.
var objectContext = ((IObjectContextAdapter)db).ObjectContext;
var objectStateManager = objectContext.ObjectStateManager;
var fieldInfo = objectStateManager.GetType().GetField("_entriesWithConceptualNulls", BindingFlags.Instance | BindingFlags.NonPublic);
var conceptualNulls = fieldInfo.GetValue(objectStateManager);

#endif

conceptualNulls is a HashSet<EntityEntry>, EntityEntry是一个内部类,因此您只能检查调试器中的集合以了解冲突的实体。仅用于诊断目的!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

由于一个或多个外键属性不可为空,因此无法更改该关系 的相关文章

随机推荐

  • 使用 boost::asio::use_future 增强 asio:async_read()

    打电话时asio async read 使用 future 有没有办法获取当 a 时传输的字节数boost asio error eof出现异常 似乎在很多情况下 即使对等方断开连接 人们也希望传输数据 例如 namespace ba bo
  • 具有自定义背景图像的 Google 地图

    我希望找到一种方法来创建带有自定义背景图像的谷歌地图实例 我看过一些示例 下面链接 但没有找到任何有关如何执行此操作的文档 我希望有人能帮助我解决这个问题 Thanks 简单的例子 http www obsidianportal com c
  • 恢复/重置默认 Xcode 字体配色方案?

    所以我尝试单击 T 却不小心单击了 XCode 字体首选项中的 颜色 框 我已经处于 默认 状态 现在我正在尝试恢复它 我发现这是不可能的 我被其他程序中存在的 重置默认值 按钮宠坏了 除了重装还有什么办法吗 是的 我偏爱白色背景 随着时间
  • 什么时候适合使用C作为面向对象语言?

    关于如何使用 C 来模拟面向对象的概念 有很多优秀的答案 仅举几例 C 具有抽象数据类型的双链表 https stackoverflow com questions 3274472 c double linked list with abs
  • 设置animationDidStopSelector:在UIView的动画委托上

    我认为在过去一年半的 iPhone 开发经验中我一直在做这个错误 我需要一些知识渊博的澄清 您可能知道也可能不知道 使用 UIView 属性可以很容易地设置动画beginAnimations forContext 方法 并用一个包装它com
  • 如何使用正则表达式来匹配不包含多个特定单词之一的字符串?

    如何使用正则表达式来避免匹配包含多个特定单词之一的字符串 例如 字符串不应包含以下单词test nor sample sample test 我的正则表达式在某些情况下会失败 1 this is a test case 2 this is
  • 使用定义的模式生成多个动态 ID 的函数

    我正在尝试创建一个函数来生成具有定义模式的多个动态 ID 我该怎么做 跟进 Vue js 如何使用定义的模式生成多个动态 ID https stackoverflow com q 49776146 8770366 Details 我正在创建
  • 如何将 Chromium 嵌入式框架 (CEF) 与 java 集成

    我想制作一个桌面应用程序来浏览网站 我不想制作浏览器 而是制作浏览器嵌入应用程序 我尝试过JavaFx但我发现了一些问题 例如缺少对插件的支持 例如 flash pdf 查看器等 经过大量搜索后 我发现了 Chromium Embedded
  • XML:如何将一个 xml 文件的内容加载到另一个文件中

    我只是希望能够从另一个 xml 文件动态写入 xml 文件的内容 A XML包含
  • Angular 6 中 ng2-file-upload 的进度条

    我想为我的文件上传创建一个进度条 我使用的上传是 https www npmjs com package ng2 file upload https www npmjs com package ng2 file upload 应用程序组件
  • 导航抽屉项目未注册点击事件

    我正在努力让导航抽屉项目注册并启动并意图进行新活动 抽屉打开正常并正确显示 但当我单击列表中的项目时没有任何反应 这是我的代码 取自谷歌教程 mTitle mDrawerTitle getTitle mTitles getResources
  • 快速将大型 2d 矩阵融合为 3 列 data.table

    我有一个大矩阵num 1 62410 1 48010 我想要一个长格式的 data table e g Var1 Var2 value 1 1 1 4227 786 2 2 1 4211 908 3 3 1 4197 034 4 4 1 4
  • Javascript 按空格分隔,但不按引号分隔

    目标是在空格处分割字符串 但不分割引号中的文本数据或将其与相邻文本分开 输入实际上是一个包含值对列表的字符串 如果 value 值包含空格 则将其括在引号中 我需要一个返回值对元素数组的函数 如下例所示 输入示例 a 0 b 1 moo f
  • 使用 UCLIBC 交叉编译 PHP

    这是一个转发 之前的帖子已关闭 移至 SERVERFAULT 并再次关闭 我认为这篇文章是一个有效的堆栈溢出问题 因为我认为它是由一些 automake 编译 链接错误引起的 这是一个编程问题而不是服务器管理问题 我会检查 uClibc 的
  • Monogame:WAV 无法播放

    这是 MonoGame 3 4 我通过 VS2013 使用它 我正在使用 mgcb 编译我的 WAV 文件 就像我的纹理一样 MGCB 工作正常 但是当涉及到使用SoundEffect类 它不播放任何内容 没有例外并且SoundEffect
  • CKEDITOR,在文本编辑器 onLoad 上自动聚焦

    有人知道如何在页面加载时自动聚焦于 CKEDITOR 文本区域吗 目前 用户必须先单击文本区域才能开始输入 像 Google 一样 我希望加载页面 并且用户可以立即开始输入 而无需单击文本区域 这是启动 CKEDITOR 的当前代码
  • webRTC - 视频导致互联网上的通话中断

    更新1 我尝试像这样改变视频约束 var mediaConstraints audio true We want an audio track video width min 160 ideal 320 max 640 height min
  • 浏览器使用哪种等宽字体?

    对于 CSS 如果您指定font family monospace 我的理解是浏览器选择其默认 首选等宽字体 如果这是正确的 您如何确定您的浏览器正在使用哪种等宽字体 可以使用 5 个通用系列 serif sans serif cursiv
  • 在 Notepad++ 中显示不匹配的 html 标签

    有没有办法在 Notepad 中突出显示不匹配的 HTML 标签 例如 如果我有以下 HTML 我想要标签以某种方式突出显
  • 由于一个或多个外键属性不可为空,因此无法更改该关系

    使用 EF 更新期间出现以下错误 操作失败 无法更改关系 因为一个或多个外键属性不可为空 当关系发生更改时 相关的外键属性将设置为空值 如果外键不支持空值 则必须定义新关系 必须为外键属性分配另一个非空值 或者必须删除不相关的对象 有没有g