实体框架代码首先:循环或多个级联路径

时间:2015-03-15 15:02:09

标签: c# sql-server entity-framework ef-fluent-api

我有一个Booking类,它有一个预订联系人(Person)和一组导航属性(People),它们通过连接表链接到另一组导航属性({{1在Bookings中。}如何为预订联系人关系启用级联删除生成Person表?当我将它从流畅的API代码中删除时(启用了级联删除的默认设置),我从迁移中收到以下错误消息:

  

引入FOREIGN KEY约束   'BookingPeople'表上的'FK_dbo.BookingPeople_dbo.People_PersonID'   可能会导致循环或多个级联路径。指定ON DELETE NO   ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY   约束

     

无法创建约束或索引。查看以前的错误。

Booking

1 个答案:

答案 0 :(得分:20)

问题是您有多个级联删除路径,可能会尝试删除数据库中BookingPeople表中的同一行。

您可以使用Fluent API在一对多关系中禁用级联删除来避免此类不明确的删除路径:

    modelBuilder.Entity<Booking>()
                .HasRequired(s => s.Contact)
                .WithMany(s => s.aBookings)
                .HasForeignKey(s => s.ContactId)
                .WillCascadeOnDelete(false);

或者通过将关系定义为可选(使用可为空的外键,但无法使用Fluent Api配置与级联删除的关系)。

     modelBuilder.Entity<Booking>()
            .HasOptional(s => s.Contact)
            .WithMany(s => s.aBookings)
            .HasForeignKey(s => s.ContactId);// ContactId is a nullable FK property

此外,您可以使用以下命令删除级联删除约定:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

或者在多对多关系的情况下:

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

如果您在删除时需要删除与Bookings相关联的所有Person,我的建议是将一对多关系配置为可选,并覆盖SaveChanges方法:

public override int SaveChanges()
{
    Bookings.Local
            .Where(r => r.ContactId == null)
            .ToList()
            .ForEach(r => Bookings.Remove(r));

    return base.SaveChanges();
 }

如果依赖实体上的外键可以为空,则Code First不会在关系上设置级联删除,并且当删除主体时,外键将设置为null。这样,您可以在SaveChanges方法中找到孤儿并删除它们