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

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

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

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

你知道我该怎么做吗?


当前回答

这是数据库触发策略类型的错误。触发器是代码,可以向级联关系(如级联删除)添加一些智能或条件。你可能需要专门化相关的表选项,比如关闭CascadeOnDelete:

protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
    modelBuilder.Entity<TableName>().HasMany(i => i.Member).WithRequired().WillCascadeOnDelete(false);
}

或者完全关闭此功能:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

其他回答

我想指出的是(从功能上)SCHEMA和DATA中的循环和/或多条路径之间有很大的区别。虽然DATA中的循环和多路径肯定会使处理复杂化并导致性能问题(“适当”处理的成本),但模式中这些特征的成本应该接近于零。

由于rdb中大多数明显的循环发生在层次结构中(组织结构图、部分、子部分等),不幸的是SQL Server假设了最坏的情况;即,模式周期==数据周期。事实上,如果您使用RI约束,您实际上无法在数据中构建一个循环!

我认为多路径问题与此类似;也就是说,模式中的多条路径并不一定意味着数据中的多条路径,但我对多路径问题的经验较少。

当然,如果SQL Server允许循环,它的深度仍然是32,但这对于大多数情况来说可能已经足够了。(可惜这不是一个数据库设置!)

“代替删除”触发器也不起作用。第二次访问表时,触发器将被忽略。所以,如果你真的想要模拟级联,你就必须在存在循环的情况下使用存储过程。但是,Instead-of-Delete-Trigger适用于多路径情况。

Celko提出了一种“更好的”表示层次结构的方法,这种方法不引入循环,但也有折衷之处。

多个套管路径的典型情况如下: 一个有两个细节的主表,我们说“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)。

我用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中找不到任何方法来做到这一点。

好运!

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

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

一些数据库,尤其是SQL Server,对形成循环的级联行为有限制。 有两种方法可以处理这种情况: 1.将一个或多个关系更改为不级联删除。 2.配置数据库时不要使用一个或多个级联删除,然后确保加载所有相关实体,以便EF Core可以执行级联行为。 请参阅此连结: 数据库级联限制