【问题标题】:Entity Framework Code First: FOREIGN KEY constraint may cause cycles or multiple cascade pathsEntity Framework Code First:FOREIGN KEY约束可能导致循环或多个级联路径
【发布时间】:2011-11-21 18:34:06
【问题描述】:

Entity Framework Code First 可以为以下 POCO 生成 DB。

public class Item {
    public int Id { get; set; }
    public string Name { get; set; }
}

public class ItemPair {
    public int Id { get; set; }

    public virtual Item FirstItem { get; set; }
    public virtual Item SecondItem { get; set; }
}

我想通过 ID 字段而不是整个“项目”类来建立与第一个和第二个项目的关系。所以:

public class ItemPair {
    public int Id { get; set; }

    public virtual Item FirstItem { get; set; }
    public int FirstItem_Id { get; set; }

    public virtual Item SecondItem { get; set; }
    public int SecondItem_Id { get; set; }
}

也可以。 编辑:这实际上不起作用。只需生成额外的 FirstItem_Id1 和 SecontItem_Id2 列。

但只需将外键属性更改为 FirstItemId、SecondItemId(不带下划线),如下所示:

public class ItemPair {
    public int Id { get; set; }

    public virtual Item FirstItem { get; set; }
    public int FirstItemId { get; set; }

    public virtual Item SecondItem { get; set; }
    public int SecondItemId { get; set; }
}

导致以下异常。

{"Introducing FOREIGN KEY constraint 'ItemPair_SecondItem' on table 'ItemPair' may cause
cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION,
or modify other FOREIGN KEY constraints.\r\nCould not create constraint. 
See previous errors."}

为什么?我能做些什么来避免这个异常。

【问题讨论】:

标签: entity-framework-4.1 ef-code-first


【解决方案1】:

我决定只删除级联删除约定。

 protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

    }

原因是:

  • 我更喜欢将记录标记为已删除或停用以进行审核。
  • 我最多只删除联结/映射表。
  • 使用 ORM 在我需要的极少数情况下循环和删除子记录相对简单。

感谢 Ladislav Mrnka 为我指明了正确的方向。

【讨论】:

  • 感谢上帝,我已经阅读了类似问题的另一个答案,并认为我需要流畅地完成所有基于属性的映射。恕我直言,EF 在默认情况下会尝试做太多事情。
  • 我也有同样的感觉,所以我也开始使用基于属性的映射。然而,我现在使用 Fluent API 映射,因为它似乎给了我更多的控制权,并且让我的 POCO 没有杂乱无章。尝试安装“Entity Framework Power Tools”并对当前数据库进行逆向工程。我想一旦你看到它生成的映射,就不会觉得如此陌生。
  • 这看起来很棒!但不幸的是,在我的情况下不起作用。我没有得到的是如何在每个关系上调用 WillCascadeOnDelete(false) 并删除此约定,并且仍然在我的 SQL 脚本(详细列表)中我可以看到它创建了有问题的约束。尽管我在流畅的映射中进行了所有工作以消除此行为,但此命令的开头是“ON DELETE CASCADE”。
  • 可能您没有在流利的映射中明确指定一个或多个关系?通过添加删除级联删除约定进行试验,看看是否可行。
【解决方案2】:

我的期望是,在第一种情况下,您的 Id 属性不会在数据库中使用,因为 FK 和 EF 将创建另外两列(您可以通过使用 ForeignKeyAttribute 强制将导航属性与 FK 属性配对来验证这一点)。在第二种情况下,EF 将正确识别您的属性,但它还将使用级联删除约定,这将导致 SQL 服务器出错。表中有两个属性指向同一个父级。实际上,在数据库中,您可以从相同的Item 创建ItemPair(两个 FK 都设置为相同的 Id)。如果两个关系都启用了级联删除,则会导致多个级联路径 => SQL Server 中不允许。

这里的解决方案是流利的映射来手动定义关系的映射方式。 Here 就是一个例子。

【讨论】:

  • 非常感谢。花了几个小时试图弄清楚。我没有想到阅读级联删除约定。
猜你喜欢
  • 2015-04-26
  • 2021-08-24
  • 2017-06-04
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 2011-05-08
  • 2013-10-22
相关资源
最近更新 更多