TransactionScope не откатывается с помощью SqlDataAdapter.Update - PullRequest
0 голосов
/ 22 июня 2010

Я использую SqlDataAdapter.Update с DataTables для обновления двух таблиц SQL в одной транзакции.Если любая из вставок не удалась, я хочу откатить все данные.Это мой код:

using (var conn = new SqlConnection(_connectionString))
{
    conn.Open();

    using (var scope = new TransactionScope())
    {
        // Insert first table
        using (var command = conn.CreateCommand())
        {
            command.CommandText =
                @"INSERT INTO TableA(Id, Data)
                  VALUES(@id, @data)";

            command.CommandType = CommandType.Text;
            command.Parameters.Add(new SqlParameter("@id", SqlDbType.Int) { SourceColumn = "Id" });
            command.Parameters.Add(new SqlParameter("@data", SqlDbType.Char) { SourceColumn = "Data" });

            var adapter = new SqlDataAdapter();
            adapter.InsertCommand = command;
            adapter.Update(tableADataTable);
        }

        // Insert second table
        using (var command = conn.CreateCommand())
        {
            command.CommandText =
                @"INSERT INTO TableB(Id, Data)
                  VALUES(@id, @data)";

            command.CommandType = CommandType.Text;
            command.Parameters.Add(new SqlParameter("@id", SqlDbType.Int) { SourceColumn = "Id" });
            command.Parameters.Add(new SqlParameter("@data", SqlDbType.Char) { SourceColumn = "Data" });

            var adapter = new SqlDataAdapter();
            adapter.InsertCommand = command;
            adapter.Update(tableBDataTable);
        }

        scope.Complete();
    }
}

Проблема, с которой я столкнулся, заключается в том, что если во время выполнения второй команды возникает исключение, данные из первой команды все еще фиксируются.Нужно ли явно откатываться?Или как должен вести себя TransactionScope при использовании SqlDataAdapter.Update?

Следует отметить, что изначально у меня было создание SqlConnection в операторе TransactionScope using, но я переместил его, так как получал ошибки, которые имел мой сервер БД.неправильно настроен для распределенных транзакций.Связан ли тот факт, что мое создание SqlConnection находится вне TransactionScope?

Ответы [ 3 ]

2 голосов
/ 22 июня 2010

Я думаю, вам нужно переместить ваш conn.Open() вызов в область транзакции, чтобы он включился в транзакцию. Также убедитесь, что в строке подключения отсутствует enslist=false;.

1 голос
/ 22 июня 2010

Попробуйте разместить SqlConnection внутри TransactionScope, после чего он автоматически подключится к транзакции.

Я думаю, что в вашем коде вам нужно вручную подключить соединение к транзакции ... просмотрите примеры в этих ссылках.

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.enlistdistributedtransaction(v=VS.71).aspx

http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx

Извините, только что поймал ваш OP - возможно, это потому, что соединение не было настроено для автоматического включения в существующие транзакции (я думаю, это член строки соединения).

Если вы не вызовете Complete (или Commit для SqlTransaction), он автоматически откатится.

Конечно, в вашем текущем примере кода - вы можете безопасно использовать объект SqlTransaction, поскольку вы не задействуете несколько соединений / баз данных.

0 голосов
/ 29 июля 2017

попробуйте вставить этот код

command.CommandText = @"SET autocommit = 0";
command.ExecuteNonQuery();

command.CommandText = @"SET sql_mode=TRADITIONAL";
command.ExecuteNonQuery();
...