实体框架代码第一:循环或多个级联路径 [英] Entity Framework Code first: cycles or multiple cascade paths

查看:140
本文介绍了实体框架代码第一:循环或多个级联路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有了一个预订触点(A )和一组导航属性(人民的舱位),通过一个连接表中链接到另一个组导航性能(预订)的。我如何生成预订表级联删除预订接触关系启用?当我离开它的流畅API代码(级联的默认设置删除已启用)我从迁移以下错误消息:




介绍FOREIGN KEY约束
对表'FK_dbo.BookingPeople_dbo.People_PersonID'BookingPeople'
可能会导致循环或多重级联路径。指定ON DELETE NO
行动或UPDATE NO ACTION,或修改其他FOREIGN KEY
约束。



无法创建约束或索引。见前面的错误




  modelBuilder.Entity<人>()
.HasMany< ;预订&将(S => s.aBookings)
.WithRequired(S => s.Contact)
.HasForeignKey(S => s.ContactId);


modelBuilder.Entity<预订>()
.HasMany(T => t.People)
.WithMany(T => t.Bookings)
.MAP(M = GT; {
m.ToTable(BookingPeople);
m.MapLeftKey(BookingID);
m.MapRightKey(是PersonID) ;
});


解决方案

的问题是你有多个路径的级联删除该最终可能会试图删除在DB的 BookingPeople 表中的同一行。



您可以避开这种暧昧删除路径无论是通过级联禁止使用在一个一对多的关系中删除流利的API

  modelBuilder.Entity<预订>()
.HasRequired(S = GT; s.Contact)
.WithMany (S = GT; s.aBookings)
.HasForeignKey(S = GT; s.ContactId)
.WillCascadeOnDelete(假);



或者通过定义的关系作为可选的(用空的外键,但不能配置的关系与级联删除使用流利的API)。

  modelBuilder.Entity<预订>()
.HasOptional(S => s.Contact)
.WithMany(S = GT; s.aBookings)
.HasForeignKey(S = GT; s.ContactId); //使用ContactID是一个可空FK财产

此外,您还可以删除级联使用删除约定:

  modelBuilder.Conventions.Remove< OneToManyCascadeDeleteConvention>(); 

或在许多一对多关系的情况:

  modelBuilder.Conventions.Remove< ManyToManyCascadeDeleteConvention>(); 

如果您需要删除所有的预订,当你删除它,我的建议是配置一个一对多的关系为可选,并覆盖的SaveChanges 方法:

 公共覆盖INT的SaveChanges()
{
Bookings.Local
。凡(R = GT; r.ContactId == NULL)
.ToList()
.ForEach(R = GT; Bookings.Remove(R));

返回base.SaveChanges();
}

如果对因实体的外键可为空,代码第一次没有设置级联删除的关系,当主被删除外键将被设置为。通过这种方式,你可以找到在的SaveChanges 法的孤儿和删除


I have a Booking class that has a booking contact (a Person) and a set of navigation properties (People) that links through a join table to another set of navigation properties (Bookings) in Person. How do I generate the Booking table with cascading deletes enabled for the booking contact relationship? When I leave it out of the fluent API code (default setting of cascade delete enabled) I get the following error message from migration:

Introducing FOREIGN KEY constraint 'FK_dbo.BookingPeople_dbo.People_PersonID' on table 'BookingPeople' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

Could not create constraint or index. See previous errors.

 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");
   });

解决方案

The problem is you have multiple paths of cascade deletes that could end trying to delete the same row in the BookingPeople table in DB.

You can avoid such ambiguous delete paths by either disabling cascading delete in the one-to-many relationship using Fluent API:

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

Or by defining the relationship as optional (with a nullable foreign key, but you can not configure the relationship with cascade delete using Fluent Api).

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

Also, you can remove the cascade delete convention by using:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

Or in the case of the many-to-many relationship:

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

If you need to delete all the Bookings asociated with a Person when you delete it, my advice is configure the one-to-many relationship as optional, and override the SaveChanges method:

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

    return base.SaveChanges();
 }

If a foreign key on the dependent entity is nullable, Code First does not set cascade delete on the relationship, and when the principal is deleted the foreign key will be set to null. This way, you can find the orphans in the SaveChanges method and delete them

这篇关于实体框架代码第一:循环或多个级联路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆