一对多卡萨德删除
本文关键字:删除 一对多 | 更新日期: 2023-09-27 18:33:17
删除父记录时,我希望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
}
然后我需要将以下内容添加到 OnModelCreate 事件中:
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.3 删除具有代码优先的级联 (Poco)
{
//...
modelBuilder.Entity<Parent>()
.HasMany(e => e.ParentDetails)
.WithOptional(s => s.Parent)
.WillCascadeOnDelete(true);
//...
需要注意的一点是,当您删除父实体时,上下文中的相关子实体也将发出 delete 语句。 例如,具有 1000 个子项的父项将发出 1001 条语句(父项为 1 条删除,子项为 1000 条)。 这样做是为了使上下文中的实体保持最新。
若要避免额外的子项删除,请在 SaveChanges 之前分离子项,并允许数据库中的外键执行删除操作。 如果先执行代码,则需要添加该外键关系。
有关详细信息,请参阅级联删除在 EF 中的实际工作原理。