【问题标题】:Uncommittable transaction is detected at the end of the batch. The transaction is rolled back在批处理结束时检测到不可提交的事务。事务回滚
【发布时间】:2019-09-22 08:52:55
【问题描述】:

我有一个存储过程,我使用事务从 c# 代码调用它。 当我在 C# 中运行代码(它是一个控制台应用程序)时,我没有从 catch 块中获取结果,而是抛出了一个异常:

在批处理结束时检测到不可提交的事务。这 事务被回滚。

C#代码:

using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

namespace app1
{
    class Program
    {
        static void Main(string[] args)
        {
            string res = "";
            string resDesc = "";

            res = WriteToDB(1,out resDesc);

            Console.WriteLine(res);
            Console.WriteLine(resDesc);


            Console.Read();
        }

        public static string WriteToDB(int val, out string resultDesc)
        {
            resultDesc = "";
            string result = "";
            string connectionString = ConfigurationManager.ConnectionStrings["SqlAppConnection"].ConnectionString;
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();
                SqlTransaction transaction = connection.BeginTransaction("transcation1");
                try
                {
                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.Connection = transaction.Connection;
                        cmd.Transaction = transaction;
                        cmd.CommandText = "usp_Test_Proc";
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@check", val);
                        SqlParameter res = cmd.Parameters.Add("@result", SqlDbType.Int);
                        res.Direction = ParameterDirection.Output;
                        SqlParameter resDesc = cmd.Parameters.Add("@resultDesc", SqlDbType.VarChar, 100);
                        resDesc.Direction = ParameterDirection.Output;
                        cmd.ExecuteNonQuery();
                        result = res.Value.ToString().Trim();
                        resultDesc = resDesc.Value.ToString();
                        transaction.Commit();
                    }
                }
                catch (Exception ex)
                {
                    result = "Exception";
                    resultDesc = ex.Message;
                    transaction.Rollback();
                }
            }
            return result;
        }

    }
}

存储过程:

ALTER PROCEDURE [dbo].[usp_Test_Proc] (
                                            @check        int, 
                                            @result           INT output, 
                                            @resultDesc       VARCHAR(100) 
output) 
AS 
  BEGIN 
      SET nocount ON; 
      SET xact_abort ON;             

      IF @check != 0 
        BEGIN 
            BEGIN try              
                SET @result = 0; 
                SET @resultDesc = 'aa'; 
                --RAISERROR('Error from raiserror',1,1)
                THROW 99001, 'Error from throw', 1;
            END try
            BEGIN catch 
                SET @result = 1; 
                SET @resultDesc = concat('catch block',ERROR_MESSAGE()); 
            END catch; 
        END 
        ELSE
        BEGIN
                SET @result = 0; 
                SET @resultDesc = 'done'; 
                end
  END; 

GO

当存储过程抛出错误时,我没有进入 catch 块,而是返回一个异常,说“在批处理结束时检测到不可提交的事务。事务被回滚。”

但如果我在 SSMS 中运行存储过程,它会按预期工作:

为什么我从 C# 代码调用它时结果不同?

【问题讨论】:

  • 我的存储过程中没有事务...是吗?...默认情况下有吗?我的计划是在循环中调用存储过程。如果所有成功都提交来自 .NET 代码的事务,否则能够回滚...
  • 对不起你的权利。你有一个 TRY...CATCH。
  • @WilliamXifaras 所以我应该在执行 .net 代码时从 catch 块中获取结果,对吗?
  • 查看文档docs.microsoft.com/en-us/sql/t-sql/language-elements/… 部分 Uncommittable Transactions 和 XACT_STATE
  • @psj01:我现在看到您也在从客户端开始交易,但我不建议这样做。相反,只在存储过程中开始事务。但是,在客户端的 Catch 块中,您还应该有一个 IF @@TRANCOUNT>0 ROLLBACK(如果存储过程超时并且永远不会到达 catch 块,则需要)。

标签: c# sql sql-server tsql


【解决方案1】:

这是因为你有'set xact_abort on'.. 根据documentation xact_abort 用于 指定当 Transact-SQL 语句引发运行时错误时 SQL Server 是否自动回滚当前事务。

您还需要将throw 中的“状态”值设置为-1,以便事务变得不可提交。

【讨论】:

    猜你喜欢
    • 2014-07-16
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 2013-11-20
    • 1970-01-01
    相关资源
    最近更新 更多