仅刷新单个交易中的某些实体

时间:2017-10-13 15:39:07

标签: php symfony doctrine doctrine-odm dbal

在我的应用程序中,我确实在某些时候写了一个读模型表(想想CQRS)。在这样做的同时,我还必须删除旧的读取模型。所以在任何给定的点上我都需要:

  1. 删除实体a,b,c
  2. 坚持实体x,y,z
  3. 为了在整个生命周期中维护有效的读取模型,我想将此过程封装在单个事务中。 Doctrine does provide the necessary means

    但是,我还必须保证在此过程中没有其他实体被刷新。可悲的是,调用学说$em->getConnection()->commit();似乎要冲洗整个工作单元。但根据文档,我必须称之为完成我的交易。

    我不能引入第二个实体管理器来仅仅获取我的读取模型实体,因为它们与其他实体位于相同的命名空间中,显然这不是doctrine-orm-b​​undle应该使用的方式。

    我看到的唯一另一种方法是在较低级别上工作并完全绕过EntityManager和UnitOfWork,但我想保证事务完整性,并且在没有em / ouw的情况下看不到这样做的方法。

1 个答案:

答案 0 :(得分:1)

TLDR:您的应用程序的工作方式可能会保证更新问题完全可以分为两个独立集,但这是不寻常的,并且很脆弱(在进行断言时通常甚至不正确) 。建模的正确方法是为每个集合使用单独的EntityManagers,并通过手动保护它们的互连,将“如何独立”的语义编码到系统中。

详细说明:

如果我正确理解了这个问题,那么你在这里面临一个设计缺陷。您有两组更新(一组用于读取模型,一组用于其他实体)并且您将它们混合(因为您希望两者都在同一个实体管理器中),同时您还想要将它们分开(通过单独的事务) 。一般来说,这不起作用。

例如,让我们认为非读取模型实体实例A只是在内存中创建(因此它还没有ID),并且基于此,您决定使用读取模型实体实例R来引用它。 >关系在内存中有效,但现在您希望能够仅刷新读取模型实体而不能刷新其他实体。即当你尝试持久化+刷新R时,它将引用一个不存在的外键,你的RDBMS将有望使事务失败。在高级别上,这是因为连接的内存中图形应该是整体中的一致数据,并且当您尝试将其有效更改拆分为子集时,您将重新排列这些更改的顺序隐式地,这可能会引入临时不一致,然后您的事务提交可能只是在这一点上。

当然,你可能会知道为什么这样的事情永远不会发生的一些规则以及为什么每个集合的一致状态以完全独立于另一个集合的方式得到保证。但是,你需要编写反映这种分离的代码;你可以这样做的方法是使用两个实体经理。在这种情况下,您的代码将清楚地处理两个不同的事务,它们的分离以及双方的确切程度。但即使在这种情况下,为避免更新冲突,您可能需要制定规则,概述两个集之间的单向可见性,这也意味着提交事务的顺序。这是因为连接图中的事务可以嵌套,但不能“仅重叠”,因为在每次事务提交时,您都要求ORM将事务范围的一致内存数据同步到RDBMS。

我知道你提到你不想使用两个EM,因为读模型实体“与其他实体位于同一个命名空间中,显然这不是doctrine-orm-b​​undle应该使用的方式”

  1. 命名空间并不重要。您可以在两个管理器中单独使用它们。您甚至可以互连它们,如果你a)正确合并()它们和b)满足你需要为两个EM的事务提供的上述一致性(因为现在它们正在处理一个连接的图形)
  2. 你应该详细说明你所指的是“这不是教条 - orm-b​​undle应该被使用的方式” - 可能是原始建议中的错误或建议的方式有问题适用于这个问题。
相关问题