TransactionScope 不使用 SqlDataAdapter.Update 回滚

发布于 2024-09-06 18:16:10 字数 1783 浏览 12 评论 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 的事实是否相关?

I'm using SqlDataAdapter.Update with DataTables to update two SQL tables in a single transaction. If either insert fails I want to roll back all data. This is my code:

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

The problem I'm having is that if an exception is thrown during the second command execution, data from the first command is still commited. Do I need to explicitly roll back? Or is how TransactionScope should behave when using SqlDataAdapter.Update?

Something to note is that originally I had the SqlConnection creation within the TransactionScope using statement, but I moved it out as I was receiving errors that my DB server hadn't been configured correctly for distributed transactions. Is the fact that my SqlConnection creation is outside TransactionScope related?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

白昼 2024-09-13 18:16:10

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

I think you need to move your conn.Open() call inside the transaction scope so it will enlist itself in the transaction. Also, make sure you do not have enslist=false; in your connection string.

ζ澈沫 2024-09-13 18:16:10

尝试将 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 对象,因为您不涉及多个连接/数据库。

Try placing your SqlConnection inside the TransactionScope, it should then automatically enlist in the transaction.

I think in your code, you need to manually enlist the connection into the transaction... review the examples in these links.

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

Sorry just caught your OP - perhaps it's because the connection wasn't configured to automatically enlist into existing transactions (a member of the connection string I think).

If you don't call Complete (or Commit on a SqlTransaction) it will automatically rollback.

Of course, in your current code sample - you can safely use a SqlTransaction object as you aren't involving multiple connections/databases.

复古式 2024-09-13 18:16:10

尝试插入这段代码

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

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

try inserting this code

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

command.CommandText = @"SET sql_mode=TRADITIONAL";
command.ExecuteNonQuery();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文