В чем причина «контекста транзакции, используемого другим сеансом»

Я ищу описание корня этой ошибки: «Контекст транзакции используется другим сеансом».

Иногда я получаю его на одном из моих тестов юнитов, поэтому не могу воспроизвести код провайдера. Но мне интересно, что является «по замыслу» причиной ошибки.

ОБНОВЛЕНИЕ: ошибка возвращается как SqlException из SQL Server 2008. Место, где я получаю сообщение об ошибке, кажется однопоточным. Но, вероятно, у меня есть взаимодействие с юнит-тестами, так как я получаю ошибку, когда запускаю несколько тестов одновременно (MSTest в VS2008sp1). Но провальный тест выглядит так:

создать объект и сохранить его внутри DB-транзакции (commit)создать TransactionScopeпытаясь открыть соединение - здесь я получаю SqlException с такой stacktrace:

.

System.Data.SqlClient.SqlException: Transaction context in use by another session.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
   at System.Data.SqlClient.SqlInternalConnectionTds.PropagateTransactionCookie(Byte[] cookie)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()

Я нашел эти сообщения:

http://blogs.msdn.com/,asiatech/archive/2009/08/10/system-transaction-may-fail-in-multiple-thread-environment.aspxhttp://msdn.microsoft.com/en-us/library/ff649002.aspx

Но я не могу понять, что«Несколько потоков, совместно использующих одну и ту же транзакцию в области транзакции, вызовут следующее исключение:« Контекст транзакции используется другим сеансом ».» средства. Все слова понятны, но не в этом суть.

Я действительно могу разделить системную транзакцию между потоками. И для этого есть даже специальный механизм - класс DependentTransaction и метод Transaction.DependentClone.

Я пытаюсь воспроизвести случай использования из первого поста:

Основной поток создает транзакцию DTC, получает DependentTransaction (создается с использованием Transaction.Current.DependentClone в основном потокеДочерний поток 1 включается в эту транзакцию DTC, создавая область транзакции на основе зависимой транзакции (передаваемой через конструктор)Дочерняя нить 1 открывает соединениеДочерний поток 2 включается в транзакцию DTC, создавая область транзакции на основе зависимой транзакции (передаваемой через конструктор)Дочерняя нить 2 открывает соединение

с таким кодом:

using System;
using System.Threading;
using System.Transactions;
using System.Data;
using System.Data.SqlClient;

public class Program
{
    private static string ConnectionString = "Initial Catalog=DB;Data Source=.;User ID=user;PWD=pwd;";

    public static void Main()
    {
        int MAX = 100;
        for(int i =0; i< MAX;i++)
        {
            using(var ctx = new TransactionScope())
            {
                var tx = Transaction.Current;
                // make the transaction distributed
                using (SqlConnection con1 = new SqlConnection(ConnectionString))
                using (SqlConnection con2 = new SqlConnection(ConnectionString))
                {
                    con1.Open();
                    con2.Open();
                }
                showSysTranStatus();

                DependentTransaction dtx = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
                Thread t1 = new Thread(o => workCallback(dtx));
                Thread t2 = new Thread(o => workCallback(dtx));
                t1.Start();
                t2.Start();
                t1.Join();
                t2.Join();

                ctx.Complete();
            }
            trace("root transaction completes");
        }
    }
    private static void workCallback(DependentTransaction dtx)
    {
        using(var txScope1 = new TransactionScope(dtx))
        {
            using (SqlConnection con2 = new SqlConnection(ConnectionString))
            {
                con2.Open();
                trace("connection opened");
                showDbTranStatus(con2);
            }
            txScope1.Complete();
        }   
        trace("dependant tran completes");
    }
    private static void trace(string msg)
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " : " + msg);
    }
    private static void showSysTranStatus()
    {
        string msg;
        if (Transaction.Current != null)
            msg = Transaction.Current.TransactionInformation.DistributedIdentifier.ToString();
        else
            msg = "no sys tran";
        trace( msg );
    }

    private static void showDbTranStatus(SqlConnection con)
    {
        var cmd = con.CreateCommand();
        cmd.CommandText = "SELECT 1";
        var c = cmd.ExecuteScalar();
        trace("@@TRANCOUNT = " + c);
    }
}

Сбой при вызове Complete корневого TransactionScope. Но ошибка другая: необработанное исключение: System.Transactions.TransactionInDoubtException: транзакция под вопросом. ---> Пэрид Время ожидания истекло до завершения операции или сервер не отвечает.

Подводя итог: я хочу понять, что означает «контекст транзакции, используемый другим сеансом» и как его воспроизвести.

Ответы на вопрос(0)

Ваш ответ на вопрос