Множественные операторы Dapper Execute () внутри бросков транзакции завершили NpgsqlTransaction; это больше не годное исключение - PullRequest
1 голос
/ 13 марта 2020

Я использую Dapper с Npg sql. (. net core 3.1)

Несколько connection.Execute(query, params, transaction) для одного соединения и внутри одной транзакции выдает исключение This NpgsqlTransaction has completed; it is no longer usable. при вызове commit() в конце.

Никаких исключений не возникает в каждом sql операторе execute.

Когда я отлаживал код, заметил, что свойство IsCompleted транзакции установлено в true после первого Execute () call.

То есть я не могу запустить Execute () несколько раз внутри одной транзакции?

using (var connection = new NpgsqlConnection(_connectionString)) {
              connection.Open();
             using (var tr = connection.BeginTransaction()) {
                    foreach (var script in scripts)
                    {
                        try
                        {
                            connection.Execute(script.SqlQuery, script.Params);
                        } 
                        catch (Exception e)
                        {
                            throw; //nothing crashes here
                        }
                    }

                    tr.Commit(); //NpgsqlTransaction has completed; it is no longer usable
                }
}

Когда транзакция не используется, все работает нормально, но мне это нужно


Upd.

Спасибо @ Mar c Грэвеллу за указание посмотреть на выполненный код sql.

У меня есть сценарий DDL CREATE TABLE IF NOT EXISTS Name (Column type); END;. Оператор END; здесь не был необходим, но это привело к завершению транзакции.

1 Ответ

0 голосов
/ 13 марта 2020

Добавить connection.Open() самостоятельно после создания соединения и перед созданием транзакции:

using (var connection = new NpgsqlConnection(_connectionString))
{
    connection.Open();
    using (var tr = connection.BeginTransaction())
    {

Обычно Dapper справляется с этим внутренне, но не может, если у вас есть несколько операций, которые должны быть на то же базовое соединение.


Также: сообщите Dapper о транзакции:

connection.Execute(script.SqlQuery, script.Params, transaction: tr);
...