views:

93

answers:

1

I have a transation that doesn't seem to rollback and getting a strange error. I'm using a transaction that is connected to SQL Server 2008 on a different server and MSMQ on the same server as the code. Here is an example of the code:

void MyMethod()
    {
       try
       {
           using (var outterTrans = new TransactionScope())
           {
               try
               {
                  InsertA();
                  SendTransactionMsmqMsg(new BlahObject());
               }
               catch (Exception e)
               {
                   //Exception is getting written here.
                   using (new TransactionScope(TransactionScopeOption.Suppress))                      
                      HandleException(e);

                    throw;
                }

                InsertB();
                outterTrans.Complete();
           }
        }
        catch(Exception e)
        {
            //Exception is getting written here too.
            HandleException(e);
        }
    }

    public void InsertA()
    {
       //Inserts data.
    }


    public void InsertB()
    {
       //Inserts data.
    }

    void SendTransactionMsmqMsg(object obj)
    {
         //When calling Msmq.Send I get 'The PROMOTE TRANSACTION request failed because there is no local transaction active.'
         Msmq.Send(CreateMessage(obj), MessageQueueTransactionType.Automatic);
    }

When this happens everything before SendTransactionMsmqMsg doesn't get rolled back. It's very rare this occurs too. Here is some of the stack trace too:

Type : System.Transactions.TransactionAbortedException, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    Message : The transaction has aborted.
    Source : System.Transactions
    Help link : 
    Data : System.Collections.ListDictionaryInternal
    TargetSite : Void CheckForFinishedTransaction(System.Transactions.InternalTransaction)
    Stack Trace :    at System.Transactions.TransactionStateAborted.CheckForFinishedTransaction(InternalTransaction tx)
       at System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
       at System.Transactions.Transaction.Promote()
       at System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction transaction)
       at System.Transactions.TransactionInterop.GetDtcTransaction(Transaction transaction)
       at System.Messaging.MessageQueue.StaleSafeSendMessage(MQPROPS properties, IntPtr transaction)
       at System.Messaging.MessageQueue.SendInternal(Object obj, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
       at System.Messaging.MessageQueue.Send(Object obj, MessageQueueTransactionType transactionType)
       ********Functions from my code here********

        Inner Exception
        ---------------
        Type : System.Transactions.TransactionPromotionException, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
        Message : Failure while attempting to promote transaction.
        Source : System.Data
        Help link : 
        Data : System.Collections.ListDictionaryInternal
        TargetSite : Byte[] Promote()
        Stack Trace :    at System.Data.SqlClient.SqlDelegatedTransaction.Promote()
           at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
           at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)

            Inner Exception
            ---------------
            Type : System.Data.SqlClient.SqlException, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
            Message : The PROMOTE TRANSACTION request failed because there is no local transaction active.
            Source : .Net SqlClient Data Provider
            Help link : 
            Errors : System.Data.SqlClient.SqlErrorCollection
            Class : 16
            LineNumber : 1
            Number : 3965
            Procedure : 
            Server : <machine>
            State : 1
            ErrorCode : -2146232060
            Data : System.Collections.ListDictionaryInternal
            TargetSite : Void OnError(System.Data.SqlClient.SqlException, Boolean)
            Stack Trace :    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()
               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.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
               at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
               at System.Data.SqlClient.SqlDelegatedTransaction.Promote()

I'm not sure what I'm doing wrong and what is causing this issue. I can't seem to generate this same exception and every exception I generate always rollback back. Anyone know how I may be able to generate this error at all?

thanks for everyones help!

+1  A: 

Is the DTC running on all servers involved in the work being done inside the transaction? Do all processes have proper access to it?

This post has the same error message you are getting: http://stackoverflow.com/questions/2487438/membership-getuser-within-transactionscope-throws-transactionpromotionexception

Update

Where is the message queue object being instantiated? I would try instantiating it inside of the transaction scope.

Phil Sandler
Yes, DTC is running on all servers. The commit and rollback seem to working except with this exception. It's almost like either the transaction is getting created but somehow getting removed before the MSMQ.Send call and that is the reason for error. Because the transaction was removed, the first part committed because it was a single transaction. Or TransactionScope ate an exception so it never really was part of a transaction so the first part committed because it's a single transaction and when calling MSMQ.Send it detected no transaction and that is the reason for the error.
Michael
See my update for another thing to try. Something is causing either the database call or the MSMQ send to not enlist in the transactionscope transaction.
Phil Sandler
It's getting created in the constructor object is getting used by more than one thread. Thinking about it, that may be an issue. Now that I think about it, it happens when there is a load on the server.
Michael
Looks like at least another problem I'm having is InsertA and InsertB are using different connections which it appears you can't do with TransactionScope.
Michael