【问题标题】:Check for duplicates in for loop before entity manager is flushed在刷新实体管理器之前检查 for 循环中的重复项
【发布时间】:2016-10-27 13:34:19
【问题描述】:

我有一个正在使用 for 循环处理的数据源。数据源有时可能有重复项。我正在循环数据源并创建“项目”实体。我试图避免这些重复,但我认为由于这些项目尚未发送到数据库,因此在重复检查期间找不到它们。

这是我的 for 循环:

foreach($datasource['data'] as $post){
    $dupe = $em->getRepository('AppBundle:Item')->findOneByDatasourceId($post['id']);
    if(!$dupe){
        //process the item
        $item = new Item();
        $item->setDatasourceId($post['id']);
        $em->persist($item);
    }
}

$em->flush();

这确实会找到重复项。

当数据尚未发送到数据库时,如何查找重复项?我的印象是实体经理会知道尚未推送的数据。

谢谢

【问题讨论】:

  • 如果你在坚持后刷新,你有重复吗?当然这不是一个优化的解决方案,但是您可以将插入的 id 存储在本地临时数组中并也可以签入该数组。
  • 我认为@Matteo 的解决方案性能最佳,但是您可以在Item 实体中使用UniqueEntity 约束,并在persist() 之前使用validator 服务对其进行验证。

标签: symfony duplicates entitymanager


【解决方案1】:

EntityManager::find 不检查等待持久化的项目。这些项目存储在一个工作对象单元中,理论上您可以检查它。但这有点痛苦。正如@Matteo 所建议的那样,您也可以在每次持久化后刷新,但这会影响性能。

让你拥有自己的本地缓存很容易:

$datasourceCache = [];
foreach($datasource['data'] as $post){
    $postId = $post['id'];
    if (!isset($datasourceCache[$postID] (
        $datasourceCache[$postID] = true;
        $dupe = $em->getRepository('AppBundle:Item')->findOneByDatasourceId($postId);
        if(!$dupe){
            //process the item
            $item = new Item();
            $item->setDatasourceId($postId);
            $em->persist($item);
        }
    }
}
$em->flush();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 2011-11-07
    相关资源
    最近更新 更多