我正在寻找一种方法将UnitOfWork恢复到一个干净的状态而不清楚整个事情。我仍然希望能够访问我已经加载的实体。这是我所拥有的基础,但我不确定这是否会以奇怪的方式破坏学说。
$uow = $em->getUnitOfWork();
$uow->computeChangeSets();//Can this be called once here, or should it be called in the inside loop so we get fresh information after a potential cascading refresh or persist?
foreach ($uow->getIdentityMap() as $className => $entities) {
foreach ($entities as $oid => $entity) {
if ($uow->isEntityScheduled($entity)) {
if ($uow->isScheduledForInsert($entity)) {
$uow->scheduleForDelete($entity);//Removes from the insert list without cascading delete or calling removal events
} elseif ($uow->isScheduledForUpdate($entity)) {
$em->refresh($entity);
} elseif ($uow->isScheduledForDelete($entity)) {
$em->persist($entity);
$em->refresh($entity);//Should I re-call computeChangeSets() here so I can check if the entity is now scheduled for update?
}
}
}
}
对于上下文:我正在运行批处理操作,在处理每个记录后,我会保留所有必需的更改。如果一个记录由于错误而失败,则会处理该失败,但是它会破坏该批次的其余部分:
A new entity was found through the relationship FOO#bar that was not configured to cascade persist operations for entity: otherFooBar .
由于我不需要保存处理记录失败的任何更改,因此我只想清理所有更改并保持对象图完好无损,同时继续处理批处理。
我已经阅读了学说来源,看起来这应该是正确的,但我并不熟悉Doctrine的内部。有没有人通过这种方法看到或知道缺陷/缺陷或知道更好的方法来实现这一目标?
编辑:澄清这个问题背后的原因。
当处理记录时发生错误时,这可能会使UoW / EntityManger处于不再保留而不被清除的位置。在我的特定情况下,错误使现有的已更改实体具有链接非持久实体,其中关系未配置为级联持久,这导致所有后续持久性失败。此时,如果我想继续处理批处理并跳过失败的记录,我有两个选择:
1)清除EntityManager并从数据库重新加载所有业务逻辑实体。但这意味着恢复功能不是通用的,必须进行自定义以了解每次更改时要重新加载和调整的实体。
2)使用UnitOfWork的现有功能清理EntityManager,这允许代码是通用的,不需要持续修改。
答案 0 :(得分:1)
您在示例代码中执行的操作的问题在于您使用的是标记为internal的方法。这些并非真正意图由'userland'代码使用。如果你想安全地做到这一点,最好的办法就是清除EntityManager并重新开始。
那就是说,你正在做什么看起来应该工作。您不需要调用scheduleForDelete。只需在计划插入的实体上调用detach,它就会从UnitOfWork中删除。