从存储库中删除模型(聚合根)时,也必须删除所有关联的聚合。
我正在努力在我的Entity Framework 6实现存储库模式
中实现它在我的示例中,我想从Customer
中删除CustomerRepository
。还应删除所有客户的Order
个对象。
存储库(已拆除):
public interface IRepository<T> where T : DomainEntity
{
void Remove(T item);
}
public class EntityFrameworkRepository<T> : IRepository<T> where T : DomainEntity
{
private readonly DbSet<T> dbSet;
public DbContext context;
public EntityFrameworkRepository(IUnitOfWork unitOfWork)
{
context = entityFrameworkUnitOfWork.context;
dbSet = dbSet = context.Set<T>();
}
public virtual void Remove(T item)
{
DbEntityEntry dbEntityEntry = context.Entry(item);
if (dbEntityEntry.State == EntityState.Detached)
{
dbSet.Attach(item);
}
dbSet.Remove(item);
}
}
public class EntityFrameworkUnitOfWork : IUnitOfWork
{
public readonly DbContext context;
public EntityFrameworkUnitOfWork()
{
this.context = new ReleaseContext();
}
public void Commit()
{
context.SaveChanges();
}
}
ICustomerRepository
和CustomerRepository
(EF实施):
public interface ICustomerRepository : IRepository<Customer>
{
IEnumerable<Customer> GetAllActive();
}
public class CustomerRepository : EntityFrameworkRepository<Customer>, ICustomerRepository
{
public CustomerRepository(IUnitOfWork unitOfWork)
: base(unitOfWork)
{ }
public override void Remove(Order item)
{
item.Orders.Clear();
base.Remove(item);
}
}
客户代码:
customerRepository.Remove(customer);
unitOfWork.Commit();
抛出异常:
System.InvalidOperationException:操作失败: 由于一个或多个关系无法改变 外键属性是不可为空的。当对a进行更改时 关系,相关的外键属性设置为空值。 如果外键不支持空值,则为新关系 必须定义外键属性必须另外分配 必须删除非空值或不相关的对象。
我会调用item.Orders.Clear()
来向EF表明必须删除关联。
答案 0 :(得分:2)
错误表明您的明确方法未删除子实体 你知道删除时流畅的api加法级联吗?
HasRequired(t =&gt; t.Parent).WithOptional()。WillCascadeOnDelete(true);
因此,如果删除根对象,则Db可以删除所有依赖项。 虽然这个选项并不总是可用......
由于您使用的是IRepository ... 你考虑使用像
这样的模式吗?public int DeleteWhere(Expression<Func<TPoco, bool>> predicate) {
var delList = Context.Set<TPoco>().Where(predicate);
foreach (var poco in delList) {
SetEntityState(poco, EntityState.Deleted);
}
return delList.Count;
}
var custid = 1;
var RepOrder - new Respository<Order>();
var delcnt = RepOrder.DeleteWhere(t=>t.CustomerId == custid);
MYContext.SaveChanges()
答案 1 :(得分:1)
有一个很好的做法:不要删除任何东西:) 将其标记为“已删除”。
因为为什么?向我们展示一个真正的业务需求来物理删除东西? 它不仅会降低速度(通常DB会在删除时锁定很多),导致碎片等,但在大多数情况下它是荒谬的!没有业务可以让您实际删除客户和订单列表!
商家不会删除任何内容。在实际业务中,没有人会找到与特定客户相关的所有文件并将其丢弃在粉碎机中。除非他们做了违法的事情并且FBI正在敲门:)
与熟悉计算机的业务专家(这些是真正的业务专家)交谈。他们会告诉你客户当他们不再是客户时会发生什么(也许他们被“存档”,或许是其他东西,或者可能只是什么),然后对其进行建模。 程序员通常会发明“删除”内容的概念。
此外,分析历史信息在未来的某个时间真的很有帮助!
只有必要进行物理删除时才有两个选项:
对于#1来说,空间现在不再是一个问题,因此实施删除可能需要花费更多的成本。 对于#2,无论如何你想要显式,你可能会以不同的方式管理你的数据存储。例如,您可能希望每个客户端都有一个数据库,因此您可以删除数据库和所有备份以符合规定(是的,您必须删除备份为了合法地说你不再持有被删除的数据了)
那你的案件是哪个?为什么要删除,您真正的业务要求是什么?