当我尝试向表格添加约束时遇到问题 . 我收到错误:
在表'Employee'上引入FOREIGN KEY约束'FK74988DB24B3C886'可能会导致循环或多个级联路径 . 指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束 .
我的约束是在 Code
表和 employee
表之间 . Code
表包含 Id
, Name
, FriendlyName
, Type
和 Value
. employee
有许多引用代码的字段,因此可以为每种类型的代码提供引用 .
如果删除引用的代码,我需要将字段设置为null .
我有什么想法可以做到这一点?
9 回答
SQL Server对级联路径进行简单计数,而不是试图确定是否存在任何周期,它假设最坏的并且拒绝创建引用操作(CASCADE):您可以而且应该仍然创建没有引用操作的约束 . 如果你不能改变你的设计(或者这样做会损害你的设计)那么你应该考虑使用触发器作为最后的手段 .
FWIW解析级联路径是一个复杂的问题 . 其他SQL产品将简单地忽略该问题并允许您创建循环,在这种情况下,它将是一个竞争,看看哪个将覆盖最后的值,可能是由于设计者的无知(例如ACE / Jet这样做) . 我理解一些SQL产品将尝试解决简单的情况 . 事实仍然是,SQL Server甚至没有尝试,通过禁止多条路径播放它超安全,至少它告诉你 .
具有多个级联路径的典型情况是:具有两个细节的主表,例如“Master”和“Detail1”和“Detail2” . 这两个细节都是级联删除 . 到目前为止没有问题 . 但是,如果两个细节与其他一些表(例如“SomeOtherTable”)具有一对多的关系,那该怎么办呢? SomeOtherTable有一个Detail1ID列和一个Detail2ID列 .
换句话说:SomeOtherTable中的一些记录与Detail1-records链接,SomeOtherTable中的一些记录与Detail2记录链接 . 即使保证SomeOtherTable记录永远不属于两个细节,现在也不可能为这两个细节制作SomeOhterTable的记录级联删除,因为从Master到SomeOtherTable有多个级联路径(一个通过Detail1,一个通过Detail2) . 现在你可能已经理解了这一点 . 这是一个可能的解决方案:
所有ID字段都是关键字段和自动递增 . 关键在于Detail表的DetailMainId字段 . 这些字段既是关键的,也是参考的约束 . 现在可以通过仅删除主记录来级联删除所有内容 . 缺点是每个detail1-record和每个detail2记录都必须有一个DetailMain记录(实际上是先创建记录以获得正确且唯一的id) .
我会指出(功能上)在SCHEMA和DATA中循环和/或多个路径之间存在巨大差异 . 虽然DATA中的循环和可能的多路径肯定会使处理变得复杂并导致性能问题(“正确”处理的成本),但架构中这些特性的成本应该接近于零 .
由于RDB中的大多数表观周期都出现在层次结构(组织结构图,部分,子部分等)中,因此不幸的是SQL Server假设最糟糕;即,模式周期==数据周期 . 实际上,如果您使用RI约束,则无法在数据中实际构建循环!
我怀疑多径问题是类似的;即,模式中的多个路径不一定意味着数据中的多个路径,但我对多路径问题的经验较少 .
当然,如果SQL Server确实允许循环,那么'd still be subject to a depth of 32, but that'对于大多数情况来说可能是足够的 . (太糟糕了,但这不是数据库设置!)
“而不是删除”触发器也不起作用 . 第二次访问表时,将忽略触发器 . 因此,如果您真的想要模拟级联,则必须在存在循环的情况下使用存储过程 . 但是,替代删除触发器适用于多路径情况 .
Celko提出了一种“更好”的方式来表示不引入周期的层次结构,但存在权衡 .
有一篇文章介绍了如何使用触发器执行多个删除路径 . 也许这对复杂场景很有用 .
http://www.mssqltips.com/sqlservertip/2733/solving-the-sql-server-multiple-cascade-path-issue-with-a-trigger/
通过它的声音,您在一个现有的外键上有一个OnDelete / OnUpdate操作,它将修改您的代码表 .
因此,通过创建此外键,您将创建一个循环问题,
例如 . 更新员工,导致代码由On Update Action更改,导致Employees被On Update Action更改......等等...
如果您发布两个表的表定义,以及您的外键/约束定义,我们应该能够告诉您问题出在哪里......
这是因为Emplyee可能有其他实体的集合说资格和资格可能有其他一些收集大学,例如
}
}
}
在DataContext上,它可能如下所示
}
在这种情况下,从员工到资格,从资格到大学都有链条 . 所以它给我带来了同样的例外 .
当我改变时,它对我有用
至
这是类型数据库触发器策略的错误 . A trigger is code and can add some intelligences or conditions to a Cascade relation like Cascade Deletion. 您可能需要专门设置相关的表选项,例如关闭CascadeOnDelete:
或者完全关闭此功能:
触发器是解决此问题的方法:
使用ASP.NET Core 2.0和EF Core 2.0遇到此问题的解决方案是按顺序执行以下操作:
在程序包管理控制台(PMC)中运行
update-database
命令以创建数据库(这会导致"Introducing FOREIGN KEY constraint ... may cause cycles or multiple cascade paths."错误)在PMC中运行
script-migration -Idempotent
命令以创建可以运行的脚本,而不管现有的表/约束获取生成的脚本并找到
ON DELETE CASCADE
并替换为ON DELETE NO ACTION
对数据库执行修改后的SQL
现在,您的迁移应该是最新的,并且不应发生级联删除 .
太糟糕了,我无法在Entity Framework Core 2.0中找到任何方法 .
祝好运!