【问题标题】:TransactionScope and rollbackTransactionScope 和回滚
【发布时间】:2014-04-21 09:19:44
【问题描述】:

考虑以下表格方案:

T2 --> T1 <-- T3

T2 指的是 T1,T3 指的是 T1,因此我无法从 T1 中删除在 T2 或 T3 中引用的行。

现在,使用以下代码:

using (var sqlConnection = new SqlConnection(ConnectionString))
{
    sqlConnection.Open();

    using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
    {
        sqlCommand.CommandText = "USE [TransactionScopeTests]; DELETE FROM T3; DELETE FROM T1;"; // DELETE FROM T1 will cause violation of integrity, because rows from T2 are still using rows from T1.

        sqlCommand.ExecuteNonQuery();
    } 
}

此代码在 SQL Server 2014 LocalDb 或 Sql Server 2012 Developer 版本上执行会产生相同的结果。表 T3 是空的,但表 T1 保持不变。

将探查器连接到此查询会执行以下 SQL:

Audit Login:

-- network protocol: Named Pipes
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed

然后SQL:BatchStarting

USE [TransactionScopeTests]; DELETE FROM T3; DELETE FROM T1;

然后是Audit Logout,然后是RPC:Completed

exec sp_reset_connection 

查看表格,T3 是空的,T1 不是。

但是,如果我们将代码包装在 TransactionScope 中:

using (var transactionScope = new TransactionScope())
{
    using (var sqlConnection = new SqlConnection(ConnectionString))
    {
        sqlConnection.Open();

        using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
        {
            sqlCommand.CommandText = "USE [TransactionScopeTests]; DELETE FROM T3; DELETE FROM T1;";

            sqlCommand.ExecuteNonQuery();
        }

        transactionScope.Complete();
    }
}

这将导致正确的行为。当连接关闭时,事务被回滚。

然而,困扰我的是在分析发送的 SQL 时我看不到这种行为。我期待使用BEGIN TRANSET XACT_ABORT ON 或类似的东西打开一个连接,但我看不出有什么区别(我确实将输出保存到文本文件并将它们与 difftool 进行比较,它们与信。)

这是分析器的输出:

Audit Login:

-- network protocol: Named Pipes
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed

然后SQL:BatchStarting

USE [TransactionScopeTests]; DELETE FROM T3; DELETE FROM T1;

然后是审核Logout,然后是RPC:Completed

exec sp_reset_connection 

但是,在这种情况下,T3 会恢复到原来的状态,因为整个语句都失败了。

谁能详细说明.NET 如何确保代码在事务中执行?

【问题讨论】:

    标签: c# transactions transactionscope


    【解决方案1】:

    尝试将您的查询更改为:

    SELECT @@OPTIONS USE [TransactionScopeTests]; DELETE FROM T3; DELETE FROM T1;

    您应该在会话级别看到不同的选项,因为这是事务范围改变的内容。试一试,选项应该会有所不同!

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 2011-02-14
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多