0

親レコードを削除するときに、EF で子レコードを削除し、次のことを行う必要はありません。

public Foo
{
    [Key]
    public int FooID { get; set; }
    public string Foo_Name { get; set; }
    //One to many with bar
    public virtual  List<Bar> Bar_List { get; set; }
}

public Bar
{
    [Key]
    public int BarID { get; set; }
    public string Bar_Name { get; set; }
    //One to Many with baz
    public virtual List<Baz> Baz_List { get; set; }
}

public Baz
{
    [Key]
    public int BazID { get; set; }
    public string Baz_Name { get; set; }
}

これは、子レコードを削除するために私が行っていることです

using(var context = new FooBarBazContext())
{
    var Foo_List = context.Foos.Where(w => w.Foo_Name == "FooName1234").ToList();

    foreach(var foo in Foo_List)
    {
         foreach(var bar in foo.Bar_List)
         {
              bar.Baz_List.ToList().ForEach(i => context.Bazs.Remove(i));
         }
         foo.Bar_List.ToList().ForEach(i => context.Bars.Remove(i));
         context.Foos.Remove(foo);
         context.Entry<Foo>(foo).State = EntityState.Deleted;
         context.SaveChanges();
    }
}

編集 - 解決策

各子オブジェクトに親ナビゲーション プロパティを追加する必要がありました。

public Foo
{
    [Key]
    public int FooID { get; set; }
    public string Foo_Name { get; set; }
    //One to many with bar
    public virtual  List<Bar> Bar_List { get; set; }
}

public Bar
{
    [Key]
    public int BarID { get; set; }
    public string Bar_Name { get; set; }
    //One to Many with baz
    public virtual List<Baz> Baz_List { get; set; }
    public virtual Foo FooObject [ get; set; } //<-- Navigation property for Foo
}

public Baz
{
    [Key]
    public int BazID { get; set; }
    public string Baz_Name { get; set; }
    public virtual Bar BarObject { get; set; } //<-- Navigation property for Bar
}

次に、OnModelCreating イベントに以下を追加する必要がありました。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Foo>().HasKey(x => x.FooID)
                               .HasMany(x => x.Bar_List)
                               .WithOptional(x => x.FooObject)
                               .WillCascadeOnDelete(true);

     modelBuilder.Entity<Bar>().HasKey(x => x.BarID)
                               .HasMany(x => x.Baz_List)
                               .WithOptional(x => x.BarObject)
                               .WillCascadeOnDelete(true);

     base.OnModelCreating(modelBuilder);
}

そして今、EF は私に代わってすべての面倒な作業を行います。

var foosToRemove = context.Foos.Where(w => w.Foo_Name == "FooName1234").ToList();

foreach (var fooToRemove in foosToRemove)
{
      context.Entry<Foo>(fooToRemove).State = EntityState.Deleted;
}
int results = context.SaveChanges();
4

1 に答える 1

1

エンティティでカスケード削除を設定する必要があります。

Entity Framework 4.3 コードを先に削除するカスケード (Poco)を参照してください。

{
//...
modelBuilder.Entity<Parent>()
    .HasMany(e => e.ParentDetails)
    .WithOptional(s => s.Parent)
    .WillCascadeOnDelete(true);
//...

親を削除すると、コンテキスト内の関連する子エンティティも削除ステートメントを発行することに注意してください。たとえば、1000 人の子を持つ親は、1001 ステートメントを発行します (親に対して 1 つの削除、子に対して 1000)。これは、コンテキスト内のエンティティを最新の状態に保つために行われます。

余分な子の削除を回避するには、SaveChanges の前に子をデタッチし、データベースの外部キーが削除できるようにします。最初にコードを作成する場合は、その外部キー関係を追加する必要があります。

詳細については、「EFでのカスケード削除の実際の動作」を参照してください。

于 2013-09-29T16:40:08.413 に答える