实体框架代码优先5级联许多删除多个表错误(Entity Framework Code First 5

2019-07-03 20:29发布

我有这个模型

public class State
{
    public State()
    {
        this.Promotions = new List<Promotion>();
        this.Branches = new List<Branch>();
        this.Stores = new List<Store>();
    }

    public int Id { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Promotion> Promotions { get; set; }
    public virtual ICollection<Store> Stores { get; set; }
    public virtual ICollection<Branch> Branches { get; set; }
}

public class Store
{
    public Store()
    {
        this.Promotions = new List<Promotion>();
        this.Branches = new List<Branch>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Promotion> Promotions { get; set; }
    public virtual ICollection<Branch> Branches { get; set; }

    public int StateId { get; set; } // Foreign key
    public virtual State State { get; set; } // Navigation Property
}

public class Branch
{
    public Branch()
    {
        this.Promotions = new List<Promotion>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public int StoreId { get; set; } // Foreign key
    public int StateId { get; set; } // Foreign key

    public virtual Store Store { get; set; } // Navigation Property
    public virtual State State { get; set; } // Navigation Property

    public virtual ICollection<Promotion> Promotions { get; set; }
}

    public class Promotion
{
    public Promotion()
    {
        this.Stores = new List<Store>();
        this.Branches = new List<Branch>();
        this.Productos = new List<Producto>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public int StateId { get; set; }

    public virtual ICollection<Store> Stores { get; set; }
    public virtual ICollection<Branch> Branches { get; set; }
    public virtual ICollection<Product> Products { get; set; }

    public virtual State State { get; set; }

}

这在我的背景:

// State
modelBuilder.Entity<State>()
    .HasMany(p => p.Promotions)
    .WithRequired(e => e.State)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<State>()
    .HasMany(s => s.Branches)
    .WithRequired(e => e.State)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<State>()
   .HasMany(e => e.Stores)
   .WithRequired(e => e.State)
   .WillCascadeOnDelete(true);

 // Store
modelBuilder.Entity<Store>()
    .HasMany(b => b.Branches)
    .WithRequired(s => s.Store)
    .WillCascadeOnDelete(true);

// Many to many
modelBuilder.Entity<Store>().
  HasMany(p => p.Promotions).
  WithMany(s => s.Stores).
  Map(
   m =>
   {
       m.MapLeftKey("StoreId");
       m.MapRightKey("PromotionId");
       m.ToTable("Store_Promotion");
   });

modelBuilder.Entity<Promotion>().
 HasMany(e => e.Products).
 WithMany(p => p.Promotiones).
 Map(
  m =>
  {
      m.MapLeftKey("PromotionId");
      m.MapRightKey("ProductoId");
      m.ToTable("Promotion_Producto");
  });

modelBuilder.Entity<Branch>().
 HasMany(p => p.Promotiones).
 WithMany(b => b.Branches).
 Map(
  m =>
  {
      m.MapLeftKey("BranchId");
      m.MapRightKey("PromotionId");
      m.ToTable("Branch_Promotion");
  });

现在,如果我(在流利的映射前三)打开国家的超过一个WillCascadeOnDelete我得到的错误

测试方法Proj.Data.Tests.UnitTest1.TestPromotion抛出异常:
System.Data.SqlClient.SqlException:将外键约束“FK_dbo.Branch_dbo.Store_StoreId”上表“分支”可能会导致循环或多个级联路径。 指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他外键约束。 无法创建约束。 请参阅以前的错误。

我知道,我已经从朱莉·勒曼的书阅读:

有些数据库(包括SQL Server)不支持指定级联删除指向同一个表倍数关系

至于它,因为很多发生在许多关系表有级联删除从两个相关的表来。

所以,我的问题是:在这里,唯一的选择是关闭的父表级联删除和手动处理的关系表中删除? 是不是有从实体框架5对此有何解决办法?

Answer 1:

好吧,我明白这个问题。 这是不是有一个多对多的关系,这个问题是这样的

State -> Promotion -> PromotionStore
State -> Branch -> BranchPromotion
State -> Store -> StorePromotion

然后存储,分支和存储有FK到国家。 所以,如果我删除一个国家PromotionStore可以通过第一和第三的可能性达到。

我落得这样做是关闭级联删除国家和手动删除相关的记录是这样的:

public override void Delete(State state)
{
   DbContext.Entry(state).Collection(x => x.Promotions).Load();
   DbContext.Entry(state).Collection(x => x.Stores).Load();
   DbContext.Entry(state).Collection(x => x.Branches).Load();

   var associatedPromotions = state.Promotions.Where(p => p.StateId == state.Id);
   associatedPromotions.ToList().ForEach(r => DbContext.Set<Promotion>().Remove(r));

   var associatedStores = state.Stores.Where(e => e.StateId == state.Id);
   associatedStores.ToList().ForEach(e => DbContext.Set<Store>().Remove(e));

   var associatedBranches = state.Branches.Where(s => s.StateId == state.Id);
   associatedBranches.ToList().ForEach(s => DbContext.Set<Branch>().Remove(s));

   base.Delete(state);
}


文章来源: Entity Framework Code First 5 Cascade Delete on many to many tables error