Итерация запроса доктрины не работает на MS SQL Server - новая транзакция не разрешена - PullRequest
0 голосов
/ 31 мая 2019

Я пытаюсь перебрать результаты и удалить их с помощью диспетчера объектов, как описано в https://www.doctrine -project.org / projects / doctrine-orm / en / 2.6 / reference / batch-processing.html# iterating-results

Однако при вызове flush() я получаю следующую ошибку:

Неустранимая ошибка PHP: Uncaught Doctrine \ DBAL \ Driver \SQLSrv \ SQLSrvException: SQLSTATE [42000, 3988]: [Microsoft] [Драйвер ODBC 13 для SQL Server] [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 голосов
/ 31 мая 2019

Проблема заключается в том, что 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;
}
...