我正在创建一个代码,我想在其中使用cascade删除父对象及其所有子对象,以减少正在执行的删除操作的数量。
所以我有这样的实体
public class Parent
{
public long ParentId { get; set; }
public string ParentName { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
并且子实体看起来像
public class Child
{
public long ChildId { get; set; }
public long? ParentId { get; set; }
public string ChildName { get; set; }
}
我创建TypeConfiguration
以使用级联删除
public class ParentTypeConfiguration : EntityTypeConfiguration<Parent>
{
public ParentTypeConfiguration()
{
this.ToTable("Parents");
this.HasKey(c => c.ParentId);
this.HasMany(c => c.Children)
.WithOptional()
.HasForeignKey(p => p.ParentId)
.WillCascadeOnDelete(true);
}
}
然后我准备好了。到目前为止一切都很好。
我创建了一个类似下面的测试,看看我做的一切都很好......
[TestMethod]
public void RemoveParentEntity()
{
var parent = new Parent() { ParentName = "name" };
parent.Children = new Collection<Child>();
parent.Children.Add(new Child() { ChildName = "child1" });
parent.Children.Add(new Child() { ChildName = "child2" });
var unitOfWork = new MyUnitOfWork();
var repo = new ParentRepository(unitOfWork);
var count = repo.GetAll().Count();
repo.Add(parent);
repo.UnitOfWork.Commit();
//unitOfWork = new MyUnitOfWork();
//repo = new ParentRepository(unitOfWork);
repo.Remove(cadenaAprobacion);
repo.UnitOfWork.Commit();
var result = repo.GetAll().Count();
Assert.AreEqual(count, result);
}
此测试未能说:
操作失败:无法更改关系,因为 一个或多个外键属性是不可为空的。当一个 改变了关系,相关的外键属性是 设置为空值。如果外键不支持空值, 必须定义新的关系,外键属性必须是 分配了另一个非空值,或者不相关的对象必须是 删除。
所以我google / binged这个,我看到我应该使我的依赖属性可选,因为子对象正在更新。所以我在实体和TypeConfiguration
中做了这个,我得到了一个DbUpdateException
的错误,典型的我无法更新子对象等。
所以现在我很困惑。为了解决这个问题,我知道我可以做两件事:
删除父对象之前删除子对象。这将在数据库中进行多次操作,这不是我想要的。
创建新上下文,获取父实体并删除实体。这将很好地工作,这些是测试中先前评论的行。
我的问题是,如果在上下文中有子集合并且您想在EF中使用级联删除选项,那么正确的做法是什么?如何在不在数据库中进行操作的情况下从上下文中删除对象?
我确信我遇到了概念问题,我希望有人指出这一点。所以我从错误中吸取教训:)