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.
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. );
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.
hr = MQSendMessage(h, // Handle to destination queue. &msgprops, // Pointer to MQMSGPROPS // structure. pTransaction); // Pointer to transaction // object.
hr = pTransaction->Commit(0, 0, 0); -or- hr = pTransaction->Abort(0, 0, 0);
pTransaction->Release();
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(); }