【问题标题】:EF 4: How to update disconnected set of data?EF 4:如何更新断开的数据集?
【发布时间】:2011-05-05 00:52:42
【问题描述】:

我正在使用 EF 4,POCO。任务如下:拥有一长串 DomainObject 类型的数据,需要从数据库中获取并在断开连接的模式下进行更新(添加、更新、删除操作)。以后如何将更新的集合推回数据库?假设自从我们加载数据以来,表没有并行更改。我知道 context.SaveChanges() 进行更新,但问题是如何将所有更改从有点列表中放回 DbSet,或者是否有办法在断开连接模式下直接使用 DbSet?谢谢!

【问题讨论】:

    标签: entity-framework-4 poco


    【解决方案1】:

    自我跟踪实体是 EDMX + ObjectContext API 的功能,因此如果您的映射/代码依赖于 DbContext API(您提到了DbSet),您将无法使用它们。自跟踪实体是变更集模式的实现(如旧数据集)。关于 SO 的一些参考:

    如果您不使用自跟踪实体,答案非常简单 - 您必须告诉 EF 您做了哪些更改。使用分离实体后,您必须将实体附加回新上下文并手动准确说出您所做的 = 插入、更新、删除的内容以及如何更改关系。此过程中的关键组件是 ObjectContext API 中的 ObjectStateManager (context.ObjectStateManager) 或 DbContext API 中的 DbChangeTracker (context.ChangeTracker)。这在处理关系时非常困难,我们中的许多人通常使用另一个过程:我们再次加载实体图并将分离实体图的更改合并到附加实体图。一些参考资料:

    请注意,您的整个过程可能会非常缓慢,具体取决于您要执行的更新数量。原因是EF doesn't support command batching 所以每次插入、更新、删除都是在单独的数据库往返中执行的。如果您更新 100.000 个复杂对象,您可以预期 SaveChanges 的执行需要几分钟时间。

    编辑:

    在一些非常特殊的场景中,您只使用没有关系的实体,您可以使用技巧来传输有关“更改”的信息:

    public void ProcessChanges(IEnumerable<DomainObject> entities)
    {
        foreach(var entity in entities)
        {
            if (entity.Id == 0)
            {
                // New entity
            }
            else if (entity.Id > 0)
            {
                // Modified entity (you cannot say if entity war really modified,
                // you must update it always).
            }
            else
            {
                // Use negative Id (origId * -1) to mark entity as deleted
                // reverse Id and delete entity
            }
        }
    }
    

    这仅适用于具有简单键的平面对象。

    【讨论】:

    • 感谢您的帖子,您似乎在该领域有很好的经验。对,我正在使用 POCO,所以 STE 对我没有帮助。让我澄清一下,我怎么知道插入或更新了 DomainObject 列表?看起来我需要有 2 个单独的列表来更新和添加记录,或者扩展我的 DomainObject 来存储操作信息,对吗?
    • 是的,您需要将该信息作为第二个数据结构或在域对象中传递(这实际上意味着实现您自己的 STE)。这显然是您通常不想做的事情,这就是我们经常使用我描述的方法的原因:从数据库加载实体并合并更改。但我并不是说对于非常简单的场景,这是唯一的方法,您可以使用一些技巧来传输有关修改的信息 - 我将在我的答案中添加示例。
    • 让我澄清一下我的任务。也许您可以提出解决方案:1)我不需要在轮胎之间发送数据。2)它是一个普通的域实体,没有图表。3)断开的数据集是指我的域对象的常规普通列表。我可以直接使用 DbSet 吗?目的是请求 Db 一次,然后在内存中做一些复杂的处理(不是处理 DB),请求、更新和添加数据到内存结构中,这需要更多的时间直接在 DB 上完成。最后将更改推送到数据库,或者只是将它们覆盖到数据库,替换整个数据集(数据库术语中的表)。
    • 好吧,为什么必须断开连接?使用仍连接到上下文的实体并直接在 DbSet 上执行插入和删除有什么问题?
    • 每次尝试在 DbSet 中查找内容时,我都会看到数据库请求。我怎样才能避免它?如何让 DbSet 从 Db 加载所有数据并使用内存快照?
    【解决方案2】:

    【讨论】:

    • 感谢您的提示。我不知道这个功能。让我检查一下。
    • 您还可以在本书中找到自我跟踪实体的一个很好的示例:实体框架食谱:一种问题解决方法如果您在 google 上查找它,您将有一个预览,您可能会能够查看正确的示例
    • 在“Entity Framework Recipes: A Problem-Solution Approach”中查找第 9-5、9-6、9-7 和 9-9 节
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 2011-03-17
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    相关资源
    最近更新 更多