我正在尝试遍历结果并使用实体管理器将其删除,如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();
答案 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;
}