我正在使用EF5 POCO实体(数据库首先不是代码,如果这有所不同)。假设我有以下(假设的)实体类型: -
商店有许多客户和产品,订单基本上是客户和产品之间的M-M联接。
我的一个典型场景涉及检索商店实体及其所有相关客户,产品和订单。现在,在内存中,用户可以选择通过UI删除客户。作为此操作的一部分,我还希望删除客户的相关订单。
这样做是否足够: -
store.Customers.Remove(customerToDelete);
或者是否有必要“打破客户订单与其产品之间的联系”,例如: -
foreach (var order in customerToDelete.Orders)
{
order.Product.Orders.Remove(order);
}
请注意,更改不一定会立即保留回DB。用户可以继续使用此内存存储层次结构,并且仅在稍后单击“保存”按钮时保留更改。因此,如果他们继续通过UI“浏览”这种实体层次结构,并深入研究特定产品,我不希望他们看到与被删除客户相关的订单。因此,我怀疑我必须执行上述foreach
来擦除客户订单的所有痕迹?
不确定它是否与我的问题有关,但有人可以解释“End1 OnDelete”EDMX属性的作用吗?我理解cascade删除如何在SQL中工作,但不确定这个EDMX级联选项在哪里适用?
答案 0 :(得分:0)
上下文不会自动删除Customer实体拥有的订单。通常,您将在UI中显示搜索结果的只读上下文:
DbSet.Where(x => x == y).AsNoTracking()
因此,当您从数据源中删除客户时,将不会自动刷新,因为您将使用新的上下文进行更新。此模式现在通常被接受,因为您不希望处理从包含陈旧实体的上下文更新数据源所导致的不可避免的异常。最好为一组工作/范围操作创建一个新的上下文。
但是,您可以使用Fluent API
设置级联删除protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>()
.HasRequired(t => t.Department)
.WithMany(t => t.Courses)
.HasForeignKey(d => d.DepartmentID)
.WillCascadeOnDelete(false);
}
这将完成从数据源中删除订单的工作,但是通过UI可见的订单将需要以某种方式刷新/删除。如果您的订单数据非常大,那么请考虑延迟加载,因为您可以defer loading您的相关实体,直到实际访问它们为止,只要您知道自己在做什么,并且在迭代时不会意外地往返例如,集合。您在删除后手动删除实体的方法也没有问题,但是,请不要忘记单独删除关系/链接,因为这会挂起并可能导致问题。