C#7.2,.NET 4.7.1
我们得到的例外实际上是“关系无法更改,因为一个或多个外键属性是不可为空的”并且我查看了该异常的响应,但我不认为它们'相关,因为我可以在不进行任何添加/删除/更新的情况下得到此错误。
A类有许多B类,它有很多C类。
在对A执行更新之前,该方法执行此操作:
var value = db.A.Where(x => x.Identifier == updated.Identifier)
.Include(x => x.A.Select(b => b.C)).ToList();
如果我执行db.ChangeTracker.DetectChanges()并查看其条目列表,则除了其中一个预期的C对象之外,其他所有对象都已被修改。然而,比较原始值和当前值没有显示出差异。
要明确:在上述转让之前,上下文未经修改; DetectChanges并查看列表中有0个条目。如果I DetectChanges再次出现在上述行之后,该列表会有5个条目。
现在是棘手的部分,我确定问题源于何处。该方法在正常情况下工作正常,但我们正在尝试引入一个新的函数,其中A类被复制到一个新实例中。要做到这一点,我们:
A.DbId = -1; A.B.ForEach(b => {b.DbId = -1; b.C.ForEach(c => c.DbId = -1);
我认为很明显副本中出现了问题,但是查看数据库,所有参考文献似乎都是正确的;我们只是难以理解为什么我们会以这种方式看待问题。如何拉动数据导致变化?并且要明确:当我们尝试在复制后复制数据时,会发生此异常;我们在复制过程中没有发现任何问题。
配置: 一个HasMany(x => x.B)
B与其他两个定义
无关C HasRequired(x => x.B).WithMany(x => x.C).Map(x => x.MapKey(“BDbId”);
感谢阅读,如果需要任何其他信息,请告诉我。
更新: 好吧,我们停止了例外,但我们不知道为什么。上面步骤3中提到的方法在其中有一行,它将为每个B添加一个新的C.我们不希望这个行为用于新函数,因此添加了一个额外的检查以防止使用新函数和异常no更长的时间。
提供更多背景信息: 程序启动并作为其中的一部分,调用仅在非常特定的情况下执行此数据副本的函数。完成后,程序继续初始化。之后,用户可以执行导致特定对象A的WCF请求的操作。客户端修改A,然后进行WCF调用以保存这些更改。正是这次更新的调用抛出异常
编辑2:花了一些时间研究这个。数据库中的条目看起来很好,参考C回到B是正确的。我可以在不调用复制代码的情况下运行程序,因此在除了创建上下文和加载A之外什么都不做的程序的新实例中,它仍然存在这个问题。
这次我注意到了导致异常的原因:加载的A实例有B只有一个C,而在数据库中实际上有3个C引用了B.所以当我告诉Entity时检索A,它到达那些B并决定它不想要所有的Cs。有一次它只检索到1 C,从那以后我一直看到2;我不知道改变了什么。但是当你去保存A时,它显然是试图将丢失的C的FK设置为null,这是不允许的,我得到了例外。
我可以使用FK对B和C表进行选择/加入就好了,所以我不知道实体在数据库中看到的是什么,我不是。
附加信息:当在上面的步骤3中复制数据时,我将它传递给2。这些As共享6个B中的5个(每个具有不同的第六个B)。添加这些As的代码首先在处理第一个A时向B添加一个新的C,然后在处理第二个A时向同一个B添加第二个新的C.似乎只是这些B导致了麻烦,但我只是无法理解为什么这样的事情不起作用。
这是继承的代码/ db。我们已经有了模型,我们已经有了数据库,所以我认为我们不是代码或数据库;它们只是存在,然后我们有一些映射某些东西的配置。另一个具有1对N关系的类仅在数据库中定义FK。但是C不仅在数据库中定义FK,而且在配置中定义FK。我试着评论出配置定义,但它没有什么区别;仅供参考。