实体框架代码优先:FOREIGN KEY约束可能导致循环或多个级联路径

时间:2011-11-21 18:34:06

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

实体框架代码首先可以为以下POCO生成数据库。

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."}

为什么呢?我该怎么做才能避免这种异常。

2 个答案:

答案 0 :(得分:21)

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

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

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

    }

原因是:

  • 我更愿意为审核目的删除或停用记录。
  • 我最多只删除联结/映射表。
  • 使用ORM在我需要的极少数情况下循环并删除子记录是相对微不足道的。

谢谢Ladislav Mrnka指出我正确的方向。

答案 1 :(得分:17)

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

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