在学习EF时,碰巧看到链接Entity Framework Databinding with WinForms,需要对以下代码进行两次小的澄清
// Currently, the Entity Framework doesn’t mark the entities
// that are removed from a navigation property (in our example the Products)
// as deleted in the context.
// The following code uses LINQ to Objects against the Local collection
// to find all products and marks any that do not have
// a Category reference as deleted.
// The ToList call is required because otherwise
// the collection will be modified
// by the Remove call while it is being enumerated.
// In most other situations you can do LINQ to Objects directly
// against the Local property without using ToList first.
foreach (var product in _context.Products.Local.ToList())
{
if (product.Category == null)
{
_context.Products.Remove(product);
}
}
// Save the changes to the database.
this._context.SaveChanges();
1当我们从类别中删除作为产品(类别的nav属性)的子项时,product.category变为null。我们正在删除产品(类别的nav)以及实体框架工作如何将类别标记为本地集合产品中的null。
2除了枚举整个集合外,还有其他选项可以删除导航属性吗?如果否,我们只能循环浏览此特定类别下的项目以避免性能问题,我们如何更改" foreach( _context.Products.Local.ToList()中的var product"仅循环此类别下的项目。
答案 0 :(得分:1)
代码有一个重要目标:检测应删除哪些产品。要找出写这些代码的原因,请阅读以下答案。
当我从导航属性集合中删除实体时,实体框架会做什么?
实体框架不会将从导航属性集合中删除的实体标记为在上下文中删除。它只是从导航属性集合中删除实体,并通过将实体的父导航属性设置为null并使子孤立来剪切关系。
这是因为您刚刚从导航属性集合中删除了实体而不是实体集。从导航属性中删除它们意味着只切断关系。
例如,如果您在类别和产品之间存在N-N关系,则每个类别可能包含0或N个产品,并且每个产品可能属于0或N类别。然后,如果您从某个类别的导航属性集合中删除某个产品,则不想删除该产品,您只需要从该类别中删除该产品,但该产品及其与其他类别的关系应保持不变。< / p>
如何找到孤儿实体?
孤立子实体具有null值的父属性。它们仍然存在于子实体的实体集的本地存储中。所以你可以找到它们并将它们标记为删除。
在类别和产品之间的1-N关系的文章示例中,每个产品属于一个类别,并从类别的产品集合中删除它意味着删除它,因此在这种情况下,当您从子集合中删除产品时一个类别,您的目标是删除产品。因此,您应该检查Products
的{{1}}存储空间,找到Catergory
为null
的所有产品,并标记要删除的主题。
您的问题
如上所述,当您从类别的products集合中删除产品时,EF会将产品的category属性设置为null。通过这种方式,EF可以减少这种关系。
虽然目前的解决方案还可以,但是,还有其他解决方案。由于Products
的{{1}}属性类型为Category
,因此您可以订阅其ObservableCollection<T>
事件并检测删除产品,并且您可以从中删除产品。
但是,循环当前类别的CollectionChanged
是没用的,因为产品已从那里删除。