我有一个问题,当我试图添加约束到我的表。我得到了错误:

在表'Employee'上引入外键约束'FK74988DB24B3C886'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他外键约束。

我的约束是在Code表和employee表之间。Code表包含Id, Name, FriendlyName, Type和Value。雇员有许多引用代码的字段,因此每种类型的代码都有一个引用。

我需要字段被设置为空,如果引用的代码被删除。

你知道我该怎么做吗?


当前回答

多个套管路径的典型情况如下: 一个有两个细节的主表,我们说“master”和“Detail1”和“Detail2”。这两个细节都是级联删除。到目前为止还没有问题。但是,如果两个细节都与其他表(比如“SomeOtherTable”)有一对多的关系呢?SomeOtherTable有一个Detail1ID-column和一个Detail2ID-column。

Master { ID, masterfields }

Detail1 { ID, MasterID, detail1fields }

Detail2 { ID, MasterID, detail2fields }

SomeOtherTable {ID, Detail1ID, Detail2ID, someothertablefields }

In other words: some of the records in SomeOtherTable are linked with Detail1-records and some of the records in SomeOtherTable are linked with Detail2 records. Even if it is guaranteed that SomeOtherTable-records never belong to both Details, it is now impossible to make SomeOhterTable's records cascade delete for both details, because there are multiple cascading paths from Master to SomeOtherTable (one via Detail1 and one via Detail2). Now you may already have understood this. Here is a possible solution:

Master { ID, masterfields }

DetailMain { ID, MasterID }

Detail1 { DetailMainID, detail1fields }

Detail2 { DetailMainID, detail2fields }

SomeOtherTable {ID, DetailMainID, someothertablefields }

所有ID字段都是键字段和自动递增字段。问题的关键在于Detail表的DetailMainId字段。这些字段既是关键约束,又是参考约束。现在可以通过只删除主记录来级联删除所有内容。缺点是,对于每个detail1记录和每个detail2记录,还必须有一个detailmain记录(实际上是首先创建该记录以获得正确和唯一的id)。

其他回答

大量数据库更新来抵消pk:做一个数据库副本代替。

特殊用例:A公司使用与b公司具有相同模式的数据库,因为他们已经合并,所以他们希望使用单个数据库。因此,来自公司B数据库的许多表的主键必须偏移,以避免与公司A的记录发生冲突。

一种解决方案是将外键定义为ON UPDATE CASCADE,并抵消带有外键的主键。但是如果你这样做的话会有很多障碍(味精1785,味精8102,…)。

因此,我想到的一个更好的主意是简单地复制数据库,DROP和re CREATE必须有其PKs|FKs偏移量的表,并复制数据(在这样做的同时,偏移主键和外键)。

避免所有的麻烦。

有一篇文章解释了如何使用触发器执行多个删除路径。也许这对于复杂的场景很有用。

http://www.mssqltips.com/sqlservertip/2733/solving-the-sql-server-multiple-cascade-path-issue-with-a-trigger/

听起来,你有一个OnDelete/OnUpdate动作在你现有的外键之一,这将修改你的代码表。

通过创建这个外键,你会创建一个循环问题,

例如,更新Employees,导致代码被一个On Update Action改变,导致Employees被一个On Update Action改变…等等……

如果你发布了两个表的表定义,以及你的外键/约束定义,我们应该能够告诉你问题在哪里…

我用ASP解决了这个问题。NET Core 2.0和EF Core 2.0是按以下顺序执行的:

在包管理控制台(PMC)中运行update-database命令来创建数据库(这将导致“引入外键约束…”可能导致循环或多个级联路径。"错误) 在PMC中运行script-migration -Idempotent命令,创建一个可以不受现有表/约束而运行的脚本 使用结果脚本并找到ON DELETE CASCADE并替换为ON DELETE NO ACTION 对数据库执行修改后的SQL

现在,您的迁移应该是最新的,级联删除应该不会发生。

太糟糕了,我在实体框架核心2.0中找不到任何方法来做到这一点。

好运!

SQL Server对级联路径进行简单的计数,而不是试图计算是否存在任何循环,它假设最坏的情况并拒绝创建引用操作(cascade):您可以并且应该仍然在没有引用操作的情况下创建约束。如果你不能改变你的设计(或者这样做会损害一些东西),那么你应该考虑使用触发器作为最后的手段。

FWIW求解级联路径是一个复杂的问题。其他SQL产品将简单地忽略这个问题,并允许您创建循环,在这种情况下,它将是一场比赛,看看谁将最后覆盖的值,可能是设计师的无知(例如ACE/Jet这样做)。我知道一些SQL产品将尝试解决简单的情况。事实是,SQL Server甚至没有尝试,它通过禁止多个路径来保持超级安全,至少它会告诉你。

微软自己建议使用触发器而不是FK约束。