【问题标题】:One to Many Casade Deletes一对多级联删除
【发布时间】:2013-09-29 16:16:58
【问题描述】:

删除父记录时,我希望 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();

【问题讨论】:

    标签: c# ef-code-first entity-framework-5 one-to-many cascading-deletes


    【解决方案1】:

    您需要在实体上设置级联删除。

    Entity Framework 4.3 delete cascade with code first (Poco)

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

    需要注意的是,当您删除父实体时,上下文中的相关子实体也会发出删除语句。例如,有 1000 个孩子的父母将发出 1001 条语句(1 条删除用于父母,1000 条用于孩子)。这样做是为了使上下文中的实体保持最新。

    为避免额外的子删除,请在 SaveChanges 之前分离子,并允许数据库中的外键执行删除。如果您先编写代码,则需要添加该外键关系。

    请参阅How Cascade Delete Really Works in EF 了解更多信息。

    【讨论】:

    • 谢谢!这看起来应该符合要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 1970-01-01
    • 2016-05-03
    • 2016-11-09
    相关资源
    最近更新 更多