好吧,我有一对多的相关模型:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public string ChildName { get; set; }
}
我想要做的是清除Parent.Children
并从数据库中删除相关的子实体。我已经尝试过了:
数据库上下文类:
modelBuilder.Entity<Parent>()
.HasMany(p => p.Children)
.WithOptional()
.WillCascadeOnDelete(true);
这很好用,但是当我这样做时,我仍然在数据库中有Parent_Id = null
字段的冗余记录
parent.Children.Clear();
repository.InsertOrUpdate(parent);
在我的存储库类中。当我这样做时也是同样的行为:
modelBuilder.Entity<Parent>()
.HasMany(pr => pr.Children)
.WithOptional(ri => ri.Parent)
.WillCascadeOnDelete(true);
在Parent
类
Child
属性
public class Child
{
...
public Parent Parent { get; set; }
...
}
或当我做的时候
modelBuilder.Entity<Child>()
.HasOptional(p => p.Parent)
.WithMany(p => p.Children)
.HasForeignKey(p => p.Parent_Id)
.WillCascadeOnDelete(true);
在Child
类
public class Child
{
...
public int Parent_Id { get; set; }
...
}
那么,如何正确配置级联删除?或者我应该如何删除这些子实体?我认为这是一项随意的任务,但我只是遗漏了一些东西。
答案 0 :(得分:94)
在EF6中,更快的操作方法是......
context.Children.RemoveRange(parent.Children)
答案 1 :(得分:59)
级联删除在此处无效,因为您不会删除parent
,只需拨打InsertOrUpdate
即可。正确的程序是逐个删除子项,例如:
using (var context = new MyContext())
{
var parent = context.Parents.Include(p => p.Children)
.SingleOrDefault(p => p.Id == parentId);
foreach (var child in parent.Children.ToList())
context.Children.Remove(child);
context.SaveChanges();
}
答案 2 :(得分:3)
这称为“删除孤儿”。
Can EF automatically delete data that is orphaned, where the parent is not deleted?
我不知道它在EF6中是如何工作的,但是在EF Core中它可以正常工作https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete,因此您不必删除父级即可工作。
答案 3 :(得分:2)
尝试更改为
public virtual ICollection<Child> Children { get; set; }
因为需要虚拟来获得延迟加载。 如上所述 here
我认为你的parent.Children.clear不起作用,因为没有加载儿童
答案 4 :(得分:1)
如果您的对象是自引用的,则可以使用以下方法删除多对多和一对多的子对象。记得以后调用db.SaveChanges():)
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Object obj = this.db.Objects.Find(id);
this.DeleteObjectAndChildren(obj);
this.db.Objects.Remove(obj);
this.db.SaveChanges();
return this.Json(new { success = true });
}
/// <summary>
/// This deletes an object and all children, but does not commit changes to the db.
/// - MH @ 2016/08/15 14:42
/// </summary>
/// <param name="parent">
/// The object.
/// </param>
private void DeleteObjectAndChildren(Object parent)
{
// Deletes One-to-Many Children
if (parent.Things != null && parent.Things.Count > 0)
{
this.db.Things.RemoveRange(parent.Things);
}
// Deletes Self Referenced Children
if (parent.Children != null && parent.Children.Count > 0)
{
foreach (var child in parent.Children)
{
this.DeleteObjectAndChildren(child);
}
this.db.Objects.RemoveRange(parent.Children);
}
}