主义查询迭代不适用于MS SQL Server-不允许新事务

时间:2019-05-31 13:51:47

标签: php sql-server pdo doctrine-orm doctrine

我正在尝试遍历结果并使用实体管理器将其删除,如https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/batch-processing.html#iterating-results

中所述

但是,在调用flush()时出现以下错误:

  

PHP致命错误:未捕获的学说\ DBAL \ Driver \ SQLSrv \ SQLSrvException:SQLSTATE [42000,3988]:[Microsoft] [用于SQL Server的ODBC驱动程序13] [SQL Server]由于存在其他线程,因此不允许新事务在会话中运行。在D:\ inetpub \ wwwroot \ vendor \ doctrine \ dbal \ lib \ Doctrine \ DBAL \ Driver \ SQLSrv \ SQLSrvException.php:54

<?php

$batchSize = 20;
$i = 0;

$q = $em->createQuery('select u from MyProject\Model\User u WHERE credit < :minCredit');
$q->setParameter('minCredit', 20);

$iterableResult = $q->iterate();
while (($row = $iterableResult->next()) !== false) {
    $em->remove($row[0]);
    if (($i % $batchSize) === 0) {
        $em->flush();
        $em->clear();
    }
    ++$i;
}
$em->flush();

1 个答案:

答案 0 :(得分:0)

问题是因为SQL Server在迭代准备好的语句时无法开始新事务。

解决方案是开始一个包含准备好的语句的事务,然后在更改所有对象之后提交。

<?php

$conn = $em->getConnection();

$batchSize = 20;
$i = 0;

$q = $em->createQuery('select u from MyProject\Model\User u WHERE credit < :minCredit');
$q->setParameter('minCredit', 20);

$conn->beginTransaction();

try {
    $iterableResult = $q->iterate();
    while (($row = $iterableResult->next()) !== false) {
        $em->remove($row[0]);
        if (($i % $batchSize) === 0) {
            $em->flush();
            $em->clear();
        }
        ++$i;
    }
    $em->flush();

    $conn->commit();
} catch (\Exception $e) {
    $conn->rollBack();
    throw $e;
}