Sending Messages Using an MS DTC External Transaction

To send a message using a Microsoft® Distributed Transaction Coordinator (MS DTC) external transaction, the application must work with all the resource managers that are needed to complete the transaction. In the example below, the only resource manager used is MSMQ.

Note  Each MSMQ message can have no more than 4 MB of data.

    To send a message using an MS DTC external transaction
  1. Call DtcGetTransactionManager to get a transaction dispenser. For information on DtcGetTransactionManager, see the Microsoft Platform SDK.
    hr = DtcGetTransactionManager(
             NULL,                          // pszHost
             NULL,                          // pszTmName
             IID_ITransactionDispenser,     // IID of interface
             0,                             // Reserved: must be null.
             0,                             // Reserved: must be null.
             0,                             // Reserved: must be null.
             (void **)&g_pTransactionDispenser  // Pointer to pointer 
                                                // to requested 
                                                // interface.
                                     );
    
  2. Initiate the transaction.
    hr = g_pTransactionDispenser->BeginTransaction (
            0,                         // Must be null.
            ISOLATIONLEVEL_ISOLATED,   // Isolation level.
            ISOFLAG_RETAIN_DONTCARE,   // Isolation flags.
            0,                         // Pointer to transaction 
                                       // options object.
            &pTransaction);            // Pointer to a pointer to 
                                       // transaction object.
    
  3. 3.Call MQSendMessage to send message.
    hr = MQSendMessage(h,           // Handle to destination queue.
                       &msgprops,   // Pointer to MQMSGPROPS 
                                    // structure.
                        pTransaction); // Pointer to transaction 
                                       // object.
    
  4. Commit or abort the transaction.
    hr = pTransaction->Commit(0, 0, 0);
    -or-
    hr = pTransaction->Abort(0, 0, 0);
    
  5. Release the transaction object.
    pTransaction->Release();
    

Example

This example sends a single message within an MS DTC external transaction.

ITransactionDispenser   *g_pTransactionDispenser;

BOOL InitCoordinatedTransactions()
{

   //////////////////////////////
   // Get transaction dispenser.
   //////////////////////////////

   // Obtain an interface pointer from MS DTC proxy
   hr = DtcGetTransactionManager(
         NULL,                              // pszHost
         NULL,                              // pszTmName
         IID_ITransactionDispenser,         // IID of interface
         0,                                 // Reserved: must be null.
         0,                                 // Reserved: must be null.
         0,                                 // Reserved: must be null.
         (void **)&g_pTransactionDispenser  // pointer to pointer to 
                                            // requested interface.
                                 );

   if (FAILED(hr))
   {
     //
     // No Connection to DTC.
     //
   return(FALSE);
   }

   return(TRUE);

}

void TransactSend(QUEUEHANDLE h, MQMSGPROPS * pMsgProps)
{

  ITransaction            *pTransaction;
  printf ("\nStarting transaction...\n\n");

  ////////////////////////////
  // Initiate a transaction.
  ///////////////////////////

  hr = g_pTransactionDispenser->BeginTransaction (
        0,                         // Must be null.
        ISOLATIONLEVEL_ISOLATED,   // Isolation level.
        ISOFLAG_RETAIN_DONTCARE,   // Isolation flags.
        0,                         // Pointer to transaction 
                                   // options object.
        &pTransaction);            // Pointer to a pointer to 
                                   // transaction object.

      if (FAILED(hr))
      {
         Error ("BeginTransaction",hr);
      }

      // Default is to commit transaction
      BOOL fCommit = TRUE;

      /////////////////////////////////////////////
      // Call MQSendMessage to send message to 
      // the receiver side within the transaction.
      /////////////////////////////////////////////
      hr = MQSendMessage(h,           // Handle to destination queue
                         pMsgprops,   // Pointer to MQMSGPROPS 
                                      // structure.
                         pTransaction); // Pointer to transaction 
                                        // Object


      if (FAILED(hr))
      {
         printf("\nFailed in MQSendMessage(). hresult- %lxh\n", (DWORD) hr) ;
         fCommit = FALSE;     // Abort if MQSend failed
      }

      ///////////////////////////////////////////////////
      // Here the application can call other resource 
      // managers (such as SQL server) and enlist their 
      // actions in the transaction pTransaction.  If 
      // atomicity is required, set fCommit to FALSE.


      // Commit the transaction or abort it
      if (fCommit)
      {
         printf ("Committing the transaction...   ");

         hr = pTransaction->Commit(0, 0, 0);

         if (FAILED(hr))
            printf ("Failed... Transaction aborted.\n\n");
         else
            printf ("Transaction committed successfully.\n\n");

      }
      else
      {
         printf ("Aborting the transaction...   ");

         hr = pTransaction->Abort(0, 0, 0);

         if (FAILED(hr))
            Error("Transaction Abort",hr);
         else
            printf ("Transaction aborted.\n\n");
      }

      // Release the transaction
      pTransaction->Release();

  }


void CleanupTransaction()
{
   ///////////////////////////////////////////////
   // Cleanup and release the transaction object.
   ///////////////////////////////////////////////

   g_pTransactionDispenser->Release();
}