6

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

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

无法创建约束或索引。请参阅以前的错误。

 modelBuilder.Entity<Person>()
   .HasMany<Booking>(s => s.aBookings)
   .WithRequired(s => s.Contact)
   .HasForeignKey(s => s.ContactId); 


 modelBuilder.Entity<Booking>()
   .HasMany(t => t.People)
   .WithMany(t => t.Bookings)
   .Map(m => {
     m.ToTable("BookingPeople");
     m.MapLeftKey("BookingID");
     m.MapRightKey("PersonID");
   });
4

1 回答 1

25

问题是您有多个级联删除路径,这些路径可能最终试图删除BookingPeopleDB 表中的同一行。

您可以通过使用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与a关联的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方法中找到孤儿并删除它们

于 2015-03-15T21:53:25.077 回答