我正在使用EF6和通用存储库模式。最近,我试图在单个步骤中删除复合实体时遇到了问题。这里是一个简化的场景:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Parent")]
public int ParentId { get; set; }
public virtual Parent Parent { get; set; }
}
如果要删除与相关子项的父实体,我会采用以下方法:
public virtual T GetById(int id)
{
return this.DBSet.Find(id);
}
public virtual void Delete(T entity)
{
DbEntityEntry entry = this.Context.Entry(entity);
if (entry.State != EntityState.Deleted)
{
entry.State = EntityState.Deleted;
}
else
{
this.DBSet.Attach(entity);
this.DBSet.Remove(entity);
}
}
首先,我通过ID查找父对象,然后将其传递给删除方法以将其状态更改为已删除。最后,context.SaveChanges()提交了删除操作。
这个方法很好用。由于我在Children上启用了级联删除,因此find方法只会检索Parent对象,删除操作也可以正常进行。
但是,当我在Child类中添加了另一个属性时:
[ForeignKey("Gender")]
public int GenderId { get; set; }
public virtual Gender Gender { get; set; }
出于某种原因,EF在Parent.Find()方法上开始拉取相关的Children。 因此我遇到以下错误:
操作失败:无法更改关系,因为一个或多个外键属性是非空的。当对关系进行更改时,相关的外键属性将设置为null值。如果外键不支持null值,则必须定义新关系,将外键属性分配给另一个非null值,或删除不相关的对象。
即使恢复更改(删除Gender属性),问题仍然存在。我不能理解这种奇怪的行为!!
我想做的就是删除Parent对象以及Children。虽然有一些解决方案,但没有一个真正符合我的目的:
1.将LazyLoading更改为false——this.Configuration.LazyLoadingEnabled = false; 这个方法有效,但在我的实际应用程序中,我需要该属性为true。 2.先迭代所有子项并删除它们,然后再删除父项。这似乎是一个解决方法,但很冗长。 3.使用Remove()而不仅仅是将EntityState更改为Deleted。 我需要跟踪审计更改,所以EntityState在这里有帮助。
有人能解释一下为什么即使我没有使用它们,EF也会加载相关的实体吗?
Delete
来删除它。 - Sefe