C# 检测SQL Server中的回滚

C# 检测SQL Server中的回滚,c#,sql-server,transactions,ado.net,C#,Sql Server,Transactions,Ado.net,当涉及两个或多个语句时,尝试检测回滚条件。对于SqlCommand.ExecuteNonQuery方法 如果未检测到有助于计数的语句,则返回 值为-1。如果发生回滚,则返回值也是-1 我故意将-1作为引用表中具有引用完整性约束的无效项插入 string sql = $@" BEGIN TRANSACTION BEGIN TRY DELETE FROM CustomerContact WHERE CustomerId = @Id

当涉及两个或多个语句时,尝试检测回滚条件。对于
SqlCommand.ExecuteNonQuery
方法

如果未检测到有助于计数的语句,则返回 值为-1。如果发生回滚,则返回值也是-1

我故意将
-1
作为引用表中具有引用完整性约束的无效项插入

string sql = $@"
    BEGIN TRANSACTION
        BEGIN TRY
            DELETE FROM CustomerContact WHERE CustomerId = @Id
            INSERT INTO CustomerContact(CustomerId, ContactId) VALUES (3, -1)
            COMMIT TRANSACTION
        END TRY
        BEGIN CATCH
            ROLLBACK TRANSACTION
        END CATCH";

using (SqlCommand command = new SqlCommand(sql, connection))
{
    command.Connection.Open();
    command.Parameters.Add("Id", SqlDbType.Int).Value = id;
    int result = command.ExecuteNonQuery();
    Console.WriteLine(result); // -> returns affected deleted rows but not -1
}
回滚按预期工作,但我没有从
ExecuteNonQuery
获取
-1
,而是从
DELETE
操作(第一条语句)获取许多受影响的行


我之前确实使用了
SqlTransaction
,但我正在测试嵌入式基于SQL的事务的行为。

我建议您只插入
CATCH
块来指示错误和相应的回滚发生,而不是尝试检测
回滚本身

最好指定
设置XACT\u ABORT ON以确保事务在超时时立即回滚。这是因为超时发生在客户端,在客户端,API取消正在运行的查询,并阻止执行带有
回滚的CATCH块。然后,连接返回到带有打开事务的池,并且锁尚未释放。尽管当池连接被重用/重置或关闭时,事务最终将被回滚,但XACT_ABORT设置将导致立即回滚并释放资源锁

下面是我为大多数情况推荐的T-SQL事务管理和结构化错误处理模式。另外,请注意分号的广泛使用


创建一个包含这两个语句的事务并锁定,检查事务的回滚?抱歉,请您提供代码帮助。对于初学者,不要使用ExecuteOnQuery()。它只有一个非常有限的返回值。ExecuteScalar是从StoredProcess获取任何有用返回值的最小值。在一天结束的时候,函数返回值就是你想要的。如果@TRANCOUNT>0 rollback,我建议您只需插入
CATCH
块以指示错误并发生回滚
IF@@TRANCOUNT>0 rollback;投掷。另外,添加
设置XACT_ABORT ON
以确保事务在超时时立即回滚。@DanGuzman您能给我写一个答案吗?非常感谢。我是新来的。
string sql = $@"
        SET XACT_ABORT ON;
        BEGIN TRY
            BEGIN TRANSACTION;
            DELETE FROM CustomerContact WHERE CustomerId = @Id;
            INSERT INTO CustomerContact(CustomerId, ContactId) VALUES (3, -1);
            COMMIT TRANSACTION;
        END TRY
        BEGIN CATCH
            IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
            THROW;
        END CATCH";

try
{
    using (SqlCommand command = new SqlCommand(sql, connection))
    {
        command.Connection.Open();
        command.Parameters.Add("Id", SqlDbType.Int).Value = id;
        int result = command.ExecuteNonQuery();
        Console.WriteLine(result); // -> returns affected deleted rows but not -1
    }
}
catch
{
    Console.WriteLine('handle exception here');
}