This example shows the steps that a C or C++ application takes to use DB-Library to update two SQL Servers within an MS DTC transaction. It shows the OLE transaction calls for initiating and committing MS DTC transactions as well as the DB-Library call to propagate an MS DTC transaction from the application to SQL Server. Note that the complete DB-Library example is not shown here but it can be found in the Microsoft SQL Server Programmer's Toolkit.
These are the steps that the application performs:
The application passes two parameters to dbenlisttrans. The first parameter is the database process structure (DBPROC), which identifies the SQL Server connection. The second parameter is a pointer to the MS DTC transaction object. To learn more about dbenlisttrans, see What's New in SQL Server 6.5.
You cannot use the DB-Library database connections until ITransaction::Commit completes and you call dbenlisttrans to enlist in a new MS DTC transaction. If you reuse the DB-Library connection before doing this, an error will result.
Note If you have used a DB-Library connection with an MS DTC transaction and you want to use the same DB-Library connection with a local SQL Server transaction, you must first call dbenlisttrans and pass a NULL transaction. By passing a NULL transaction to the DB-Library dbenlisttrans function, you instruct SQL Server to use local SQL Server transactions.
void main(int argc, char **argv)
{
  
ITransactionDispenser    *pTransactionDispenser;
ITransaction                *pTransaction;
HRESULT                    hr = S_OK ;
TCHAR                    SqlStatement[STR_LEN*2];
  
  
// Initialize globals & validate command line arguments
InitGlobals(argc,argv);
  
// set error/msg handlers for this program
dbmsghandle((DBMSGHANDLE_PROC)msg_handler);
dberrhandle((DBERRHANDLE_PROC)err_handler);
  
// initialize LOGINREC structure
login = dblogin();
  
// Obtain the ITransactionDispenser Interface pointer
// by calling DtcGetTransactionManager()
hr = DtcGetTransactionManager(
        NULL,                 // LPTSTR pszHost,
        NULL,                // LPTSTR pszTmName,
        IID_ITransactionDispenser,    // REFIID rid,
        0,                    // DWORD dwReserved1,
        0,                    // WORD wcbReserved2,
        0,                    // void FAR * pvReserved2,
        (void **)&pTransactionDispenser     // void**    ppvObject) ;
if (FAILED (hr))
{
printf("DtcGetTransactionManager failed: %x\n", hr);
       exit (1);
}
  
// Establish connection to database on server#1
LogonToDB(&dbproc_server1,&gSrv1);
 
// Establish connection to database on server#2
LogonToDB(&dbproc_server2,&gSrv2);
  
// Loop performing distributed transactions
for (INT i = 0; i < 5; i++)
{
  
// Initiate an MS DTC transaction
hr = pTransactionDispenser->BeginTransaction(
            NULL,                // IUnknown __RPC_FAR *punkOuter,
            ISOLATIONLEVEL_ISOLATED,    // ISOLEVEL isoLevel,
            ISOFLAG_RETAIN_DONTCARE,    // ULONG isoFlags,
            NULL,                // ITransactionOptions *pOptions 
            &pTransaction        //  ITransaction **ppTransaction) ;
if (FAILED (hr))
{    
printf("BeginTransaction failed: %x\n",hr);
exit(1);
}
  
// Enlist each of the data sources on the transaction
Enlist(&gSrv1,dbproc_server1,pTransaction);
Enlist(&gSrv2,dbproc_server2,pTransaction);
  
// Generate the SQL statement to execute on each
// of the databases
sprintf(SqlStatement,
  "update authors set address = '%s_%d' where au_id = '%s'",
  gNewAddress,i,gAuthorID);
// Perform updates on both of the DBs participating
// in the transaction
ExecuteStatement(&gSrv1,dbproc_server1,SqlStatement);
ExecuteStatement(&gSrv2,dbproc_server2,SqlStatement);
  
// Commit the transaction 
hr = pTransaction->Commit(0,0,0);
if (FAILED(hr))
{
printf("pTransaction->Commit() failed: %x\n",hr);
exit(1);
}
  
// At end of each transaction, pTransaction-Release()
// must be called.
hr = pTransaction->Release();
if (FAILED(hr))
{
printf("pTransaction->Release() failed: %x\n",hr);
exit(1);
}
  
printf("Successfully committed Transaction #%d\n",i);
  
} // for 
  
  
// release the transaction dispenser
pTransactionDispenser->Release();
  
// release DBLib resources and exit
dbexit();
}
  
  
void LogonToDB(DBPROCESS **dbp, DBCONN *ptr)
{
  
DBSETLUSER(login, ptr->pszUser);
DBSETLPWD(login, ptr->pszPasswd);
DBSETLAPP(login, "example");
  
*dbp = dbopen (login, ptr->pszSrv);
if (*dbp == NULL)
{
printf ("\nLogin to server: %s failed, exiting!\n",ptr->pszSrv);
exit (ERREXIT);
}
  
/* Use the "pubs" database. */
dbuse(*dbp, "pubs");
}
  
  
void Enlist(DBCONN *ptr, DBPROCESS *dbp, ITransaction *pTransaction)
{
RETCODE rc = 0;
rc = dbenlisttrans (dbp, pTransaction);
if (FAIL == rc) 
{
printf("\ndbenlisttrans() failed: %x\n",rc);
exit(1);
}
  
}
  
  
void ExecuteStatement(DBCONN *ptr, DBPROCESS *dbp, char *pszBuf)
{
RETCODE rc = 0;
  
dbcmd(dbp,pszBuf);
rc = dbsqlexec(dbp);
if (FAIL == rc)
{
printf("dbsqlexec() failed\n");
exit(1);
}
  
rc = dbresults(dbp);
if (rc != SUCCEED)
{
printf("dbresults() failed: %x\n",rc);
exit(1);
}
}