0

我使用 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();
    }
}

我遇到的问题是,如果在第二个命令执行期间引发异常,则仍然提交来自第一个命令的数据。我需要显式回滚吗?或者在使用 SqlDataAdapter.Update 时 TransactionScope 应该如何表现?

需要注意的是,最初我在 TransactionScope using 语句中创建了 SqlConnection,但我将它移出,因为我收到错误,即我的数据库服务器没有为分布式事务正确配置。我的 SqlConnection 创建与 TransactionScope 无关吗?

4

3 回答 3

2

我认为您需要将您的conn.Open()调用移到事务范围内,以便它将自己加入事务中。另外,请确保您enslist=false;的连接字符串中没有。

于 2010-06-22T15:36:45.543 回答
1

尝试将 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(或 SqlTransaction 上的 Commit),它将自动回滚。

当然,在您当前的代码示例中 - 您可以安全地使用 SqlTransaction 对象,因为您不涉及多个连接/数据库。

于 2010-06-22T15:25:53.063 回答
0

尝试插入此代码

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

command.CommandText = @"SET sql_mode=TRADITIONAL";
command.ExecuteNonQuery();
于 2017-07-29T05:55:29.160 回答