В конце пакета обнаруживается незафиксированная транзакция.Транзакция откатывается - PullRequest
3 голосов
/ 03 мая 2019

У меня есть хранимая процедура, которую я вызываю из кода ac # с использованием транзакции.Когда я запускаю код в 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, она работает какожидается: enter image description here

Почему результат отличается, когда я вызываю его из кода C #?

1 Ответ

1 голос
/ 04 мая 2019

Это потому, что у вас есть 'set xact_abort on' .. Согласно документации xact_abort используется для Указывает, будет ли SQL Server автоматически откатывать текущую транзакцию, когда инструкция Transact-SQL вызывает ошибку во время выполнения.

Также вам необходимо установить значение 'state' в -1 в throw , чтобы транзакция стала некомпетентной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...