7

私はこのモデルを持っています

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(流暢なマッピングの最初の3つ)をオンにすると、エラーが発生します。

テストメソッドProj.Data.Tests.UnitTest1.TestPromotionが例外をスローしました:
System.Data.SqlClient.SqlException:テーブル'Branch'にFOREIGNKEY制約'FK_dbo.Branch_dbo.Store_StoreId'を導入すると、サイクルまたは複数のカスケードパスが発生する可能性があります。ON DELETENOACTIONまたはONUPDATENO ACTIONを指定するか、他のFOREIGNKEY制約を変更します。制約を作成できませんでした。以前のエラーを参照してください。

私はそれを知っています、そして私はジュリー・ラーマンの本から読みました:

一部のデータベース(SQL Serverを含む)は、同じテーブルを指すカスケード削除を指定する複数の関係をサポートしていません

多対多の関係テーブルには、関連する両方のテーブルからのカスケード削除があるためです。

だから、私の質問は:ここでの唯一の選択は、親テーブルのカスケード削除をオフにし、関係テーブルの削除を手動で処理することですか?これに対するEntityFramework5の回避策はありませんか?

4

1 に答える 1

6

わかりました、私は問題を理解しました。多対多の関係を持つことではありません。問題はこれです

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

次に、Store、Branch、Store には State への FK があります。したがって、State PromotionStore を削除すると、1 番目と 3 番目の可能性で到達できます。

私がやったことは、状態のカスケード削除をオフにし、次のように関連するレコードを手動で削除することです:

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);
}
于 2012-11-19T15:47:31.070 に答える