【问题标题】:EntityCollection Clear() and Remove() methodsEntityCollection Clear() 和 Remove() 方法
【发布时间】:2010-10-06 17:51:22
【问题描述】:

删除 EF 实体的所有集合项的正确方法是什么?在下面的代码中,DocumentItems 是文档的相关文档项的集合。此代码在 Clear() 上继续,但在 SaveChanges() 上失败,因为相关项目通过 FK 连接到它们的文档,并且 FK 是强制性的。所以我猜想它们在 Clear() 之后没有外键就一直漂浮在空中。

我是通过对每个项目调用 Remove() 的集合进行 foreach 循环来解决这个问题,还是有其他方法?

// remove existing document items to prepare for refreshing them
existing.DocumentItems.Clear();
// adds new Document Items
PrepareInvoice(existing, collection);
_repository.SaveChanges();

【问题讨论】:

    标签: entity-framework entity-framework-4


    【解决方案1】:

    这是删除集合中项目的一种方法。

    VB

    TEntityCollection.ToList().ForEach(Sub(o) ctx.DeleteObject(o))
    

    C#

    TEntityCollection.ToList().ForEach(x => ctx.DeleteObject(x))
    

    那你需要调用

    ctx.SaveChanges()
    

    【讨论】:

    • 我认为 EF 6 有一个名为 RemoveRange 的新方法,我实际上并没有使用它,但这里有一个链接到有的人:)。 stackoverflow.com/questions/21568479/…
    • RemoveRange 修复了它。谢谢。
    【解决方案2】:

    Clear 只是删除引用但不删除实体。

    你的情况

    existing.DocumentItems.Clear();  
    

    EntitySet 中的所有DocumentItems 都将被清除,但您必须删除/删除实际的DocumentItem 或失败的提交,就像您尝试在数据库中删除它一样。

    您需要循环分离任何引用,然后删除您要删除的实体(除非它的 nullable 并且在您的情况下不是)


    另外,我见过使用 clear 和 AssociationChangedHandler 来自动删除旧对象的实现。基本上,如果更改是“删除/删除”,它会在孤立对象上调用 DeleteObject()

    【讨论】:

    • 首先,我认为具有讽刺意味的是,我们正在谈论 Clear 是如何不清楚的。我的理解是它们是不同的。清除只是说删除指向(在内存中)这些对象的指针。 Remove 说从我的列表中删除并标记为删除...如果我说的任何内容无效,请纠正我。
    【解决方案3】:

    技巧:在设置父子关系时,您必须在子节点上创建一个“复合”键。这样,当您告诉父级删除 1 个或所有子级时,相关记录实际上会从数据库中删除。

    使用 Fluent API 配置复合键:

    modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });
    

    然后,删除相关的孩子:

    var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId);
    
    var childToRemove = parent.Children.First(); // Change the logic 
    parent.Children.Remove(childToRemove);
    
    // or, you can delete all children 
    // parent.Children.Clear();
    
    _context.SaveChanges();
    

    完成!

    【讨论】:

      【解决方案4】:

      是的,一岁了,但要注意一点……因为 DeleteObject 采用一个参数,它与 lambda 表达式的参数类型相同,所以您可以使用:

      entityCollection.ToList().ForEach(ctx.DeleteObject);
      

      不过,我不确定 VB 是否支持类似的语法。有人吗?

      【讨论】:

        【解决方案5】:

        只是为了回答 Nix 对答案的评论,

        在我看来,EntityCollection.Remove() 方法只标记删除关系而不是实体,就像 EntityCollection.Clear() 方法一样。

        我知道文档说该实体也将被标记为删除,但在我的测试中,我得到了我所描述的行为(谁能解释我为什么?)。

        因此,如果您的概念模型中有一对多外键约束,则无法将更改保存到持久存储中的上下文。

        我发现的唯一方法(因为我不想 CascadeDelete)是循环遍历子代并在每个子代上调用 context.DeleteObject,从而删除实体和关联关系。

        【讨论】:

          猜你喜欢
          • 2011-01-13
          • 1970-01-01
          • 2020-02-25
          • 1970-01-01
          • 2012-07-17
          • 1970-01-01
          • 2018-11-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多