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.
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();
}