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

Pau*_*uly 16 ef-code-first entity-framework-4.1

实体框架代码首先可以为以下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; }
}
Run Code Online (Sandbox Code Playgroud)

我想通过ID字段而不是整个"Item"类与First和Second项建立关系.所以:

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; }
}
Run Code Online (Sandbox Code Playgroud)

也有效. 编辑:这实际上没有用.只需生成其他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; }
}
Run Code Online (Sandbox Code Playgroud)

导致以下异常.

{"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."}
Run Code Online (Sandbox Code Playgroud)

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

Pau*_*uly 21

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

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

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

    }
Run Code Online (Sandbox Code Playgroud)

原因是:

  • 我更喜欢为审计目的标记删除或停用的记录.
  • 我最多只删除了连接/映射表.
  • 使用ORM在我需要的极少数情况下循环并删除子记录是相对微不足道的.

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


Lad*_*nka 17

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

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