Using Microsoft Transaction Server with Oracle8 Release 8.1.6 for Windows NT Part Number A73029-01 |
|
This chapter describes how to program with Microsoft Transaction Server and an Oracle8 database.
Specific topics discussed are:
When a client computer initiates a transaction request, Microsoft Transaction Server enlists the Oracle8 database to act as a resource manager (RM) in the transaction process. The focal point of the transaction process is a component of Microsoft Transaction Server called Microsoft Distributed Transaction Coordinator (MS DTC). The figure and table below provide an overview of how these and other components perform a transaction:
See the Microsoft Transaction Server Programmer's Guide in the Microsoft Transaction Server's Help file for an explanation of how to develop application components for Microsoft Transaction Server.
Regardless of the application program interface (API) you use, OCI connection pooling is used in nearly all cases to coordinate a transaction. Review the following sections for information on how a transaction is registered and OCI connection pooling is used to coordinate your transaction:
Application components that run in the Microsoft Transaction Server environment are created as dynamic link libraries (DLLs) that are registered with Microsoft Transaction Server using the Microsoft Transaction Server Explorer graphical user interface (GUI) tool. When you register the application component, you mark it as one of the following:
How you register an application component determines if it runs in a Microsoft Transaction Server-coordinated transaction.
If Your Application Component... | Then... |
---|---|
Runs in a Microsoft Transaction Server-coordinated transaction |
OCI connection pooling is always used and Microsoft Transaction Server and its MS DTC component coordinate the creation, startup, management, and commitment phases of the transaction. Microsoft Transaction Server ensures that all changes made by the component are committed if the transaction succeeds, or are aborted if the transaction fails. See section "Components Running in a Microsoft Transaction Server-Coordinated Transaction". |
Does not run in a Microsoft Transaction Server-coordinated transaction |
The component runs in a Microsoft Transaction Server environment, but its MS DTC component may or may not coordinate communication between the Oracle Service for MTS and the Oracle8 database. If your transaction is not MS DTC-coordinated, your client application must create, start, manage, and commit the transaction. See section "Components Not Running in a Microsoft Transaction Server-Coordinated Transaction, But Using MS DTC". OCI connection pooling may be used, depending upon how you program your client application and the OCI API. |
This section describes how OCI connection pooling, Microsoft Transaction Server, and MS DTC operate with application components in a Microsoft Transaction Server-coordinated transaction environment.
These actions return OCI service and environment handles to client applications.
This section describes how OCI connection pooling, Microsoft Transaction Server, and MS DTC operate with application components in this type of environment.
The following OCI functions enable you to integrate your OCI client application with Microsoft Transaction Server and an Oracle8 database. Review the following sections for information on this integration:
You must use OCI version 8.1. OCI releases earlier than 8.1 are not supported.
The only change to make in your code is in obtaining and releasing your OCI service context handle. An OCI service context handle and environment handle are acquired when you obtain a pooled OCI connection to the database with the OCI function OraMTSSvcGet(). Include the ORAMTS.H header and link with the ORAMTS.LIB library. When you are finished, call OCI function OraMTSSvcRel() to release your service context handle and environment handle. Using OraMTSSvcGet() enables you to receive connection pooling and implicit transaction support (if you registered your application component to run in a Microsoft Transaction Server transaction). See sections "OraMTSSvcGet()" and "OraMTSSvcRel()" for more information.
If you use OraMTSSvcGet() and OraMTSSvcRel(), and you did not register your component to run in a Microsoft Transaction Server transaction, you can still enlist your database in a Microsoft Transaction Server-coordinated transaction. Use OCI function OraMTSSvcEnlist() (for pooled or nonpooled connections) or, for better performance, OraMTSSvcEnlistEx() (for nonpooled connections obtained through standard OCI methods). In these cases, the MS DTC component of Microsoft Transaction Server coordinates the transaction. See sections "OraMTSSvcEnlist()" and "OraMTSSvcEnlistEx()" for more information.
Ensure that on a per process basis, you call OCIInitialize at least once before executing any other OCI calls. This initializes the OCI process environment. In addition, you must pass it the OCI_THREADED flag. If you are using Microsoft's Internet Information Server (IIS) and your components are being called as in-process libraries, then OCIInitialize is already called for you.
#include <oci.h> #include <oramts.h> #include <xolehlp.h> // other MTS relevent includes ... // prototype for the error handler. BOOL Chekerr(sword swOCIStat, OCIError *OCIErrh); // MTS component method HRESULT OCITestMethod() { IObjectContext *pObjectContext = NULL; OCIEnv *myenvh = NULL; OCISvcCtx *mysvch = NULL; OCIError *myerrh = NULL; OCIStnt *mystmh = NULL; DWORD dwStat; HRESULT hRes = S_OK; sword swOCIStat; BOOL bCommit = FALSE; char *lpzStmt = "UPDATE EMP SET SAL = SAL + 1000"; // Initialize the OCI environment first -- request OCI_THREADED OCIInitialize(OCI_THREADED, (dvoid*)NULL,NULL,NULL,NULL); // attempt to get a connection to the database via the resource dispenser OraMTSSvcGet( "scott","tiger","finprod_db",&mysvch, &myenvh, ORAMTS_CFLG_ALLDEFAULT); // validate return status if(dwStat != ORAMTS_ERR_NOERROR) { printf("error: failed to obtain a connection to the database - %ld", dwStat); goto cleanup; } // successful logon and enlistment in the MTS transaction. allocate statement // handles and other handles using the OCI environment handle myenvh .... swOCIStat = OCIHandleAlloc(myenvh, (void *)&myerrh,OCI_HTYPE_ERROR, 0 , NULL); if (Checkerr(swOCIStat, myerrh)) goto cleanup; swOCIStat = OCIHandleAlloc(myenvh, (dvoid *)&mystmh,OCI_HTYPE_STMT, 0,NULL); if (Checkerr(swOCIStat, myerrh)) goto cleanup; // prepare a DML statement OCIStmtPrepare(mystmh, myerrh, lpzStmt, lstrlen(lpzStmt), OCI_NTV_SYNTAX, OCI_DEFAULT) Checkerr(swOCIStat, myerrh); // execute the statement -- ensure that AUTOCOMMIT is not requested. OCIStmtExecute(mysvch, mystmh, myerrh, 1, 0, NULL, NULL, OCI_DEFAULT); if (Checkerr(swOCIStat, myerrh)) goto cleanup; // all's well so far choose to go for a commit bCommit = TRUE; cleanup: if (mystmh) OCIHandleFree((void*)mystmh, OCI_HTYPE_STMT); if (myerrh OCIHandleFree((void*)myerrh, OCI_HTYPE_ERROR); if (mysvch) OraMTSSvcRel(mysvch); if (bCommit) pObjectContext->SetComplete(); else pObjectContext->Abort(); return(bCommit ? S_OK : E_FAIL); }
See the ACCOUNT.VC files in the ORACLE_BASE\ORACLE_HOME\ORAMTS\ SAMPLES\ACCOUNT.VC\RELEASE directory for code samples.
This illustration provides a high-level overview of how to use the OCI functions OraMTSSvcGet(), OraMTSSvcRel(), and OraMTSSvcEnlist().
Non-COM applications (also known as standalone applications) can also use methods 2, 3, and 4 above. However, non-COM applications cannot use the Microsoft Transaction Server Explorer GUI. Method 3 can also use OraMTSSvcEnlistEx() instead of OraMTSSvcEnlist() for better performance.
OraMTSSvcGet() obtains a pooled connection (also known as an OCI service context) from the OCI connection pool. The pooled connection includes an OCI service context handle and OCI environment handle.
DWORD OraMTSSvcGet(text *lpUname, text *lpPsswd, text *lpDbnam, OCISvcCtx **pOCISvc, OCIEnv **pOCIEnv, ub4 dwConFlgs);
Returns ORAMTSERR_NOERROR upon successful acquisition of an OCI pooling connection (OCI service context).
OraMTSSvcGet() returns a pooled OCI connection to the caller, enabling a database transaction using OCI to begin. Use OraMTSSvcGet if you want to implicitly enlist the OCI connection in a transaction coordinated by Microsoft Transaction Server. In this type of transaction, Microsoft Transaction Server controls the creation, startup, management, and commitment phases of the transaction through its MS DTC component.
OraMTSSvcGet() can also be used to simply provide connection pooling without enlisting the Oracle8 database in an MTS transaction. This is done by setting OraMTSSvcGet() as follows:
OraMTSSvcGet(...,ORAMTS_CFLG_NOIMPLICIT)
In all cases where OraMTSSvcGet() is used, you must always use OraMTSSvcRel() to release the connection when you are done.
Note: Connection pooling is used regardless of whether you enlist or do not enlist your COM component in a transaction. |
Use the flags ORAMTS_CFLG_SYSDBALOGN, ORAMTS_CFLG_SYSOPRLOGN, and ORAMTS_CFLG_PRELIMAUTH when connecting as SYSDBA, SYSOPER, and INTERNAL, respectively. For instance, to obtain an enlisted connection using the INTERNAL account, call OraMTSSvcGet() as follows:
OraMTSSvcGet("INTERNAL", "oracle", "oracle", &OCISvc, &OCIEnv, ORAMTS_CFLG_ ALLDEFAULT | ORAMTS_CFLG_PRELIMAUTH);
To obtain a nonenlisted connection using the SCOTT/TIGER account, call OraMTSSvcGet() as follows:
OraMTSSvcGet("scott", "tiger", "oracle", &OCISvc, &OCIEnv, ORAMTS_CFLG_ ALLDEFAULT | ORAMTS_CFLG_NOIMPLICIT);
OraMTSSvcGet does not support placing the user name (lpUname), password (lpPsswd), and net service name syntax (lpDbname) together in the user name argument (for example, "SCOTT/TIGER@PROD_FIN"). Instead, the caller must fill in lpUname, lpPsswd, and lpDbname separately (as shown in the two examples above). Calling OraMTSSvcGet() with the user name and password as NULL strings causes external authentication (operating system authentication) to be used for the connection.
OraMTSSvcRel() releases a pooled OCI connection (OCI service context) back to the connection pool. OraMTSSvcRel() must be used to release connections that were acquired with OraMTSSvcGet().
DWORD OraMTSSvcRel(OCISvcCtx *OCISvc);
Data Type | Parameter | Description |
OCISvcCtx |
*OCISvc(IN) |
OCI service context for pooled connection |
Returns ORAMTSERR_NOERROR upon successful release of a pooled OCI connection.
An OCI pooled connection obtained through a previous call to OraMTSSvcGet() is released back to the connection pool. Once released back to the connection pool, the OCI service context, its environment handle, and all child handles are invalid.
A nontransactional client component must explicitly issue OCITransCommit() or OCITransAbort() prior to releasing a connection obtained through OraMTSSvcGet(...,...,ORAMTS_CFLG_ALLDEFAULT) back to the pool. Otherwise, all changes made in that session are rolled back. A transaction component uses the SetComplete or SetAbort methods on its Microsoft Transaction Server object context.
Components that have called OraMTSSvcGet(...,...,ORAMTS_CFLG_NOIMPLICIT) to obtain a connection resource must first de-enlist the resource if enlisted. If the connection was enlisted explicitly, pTransaction->Commit() or pTransaction->Abort() must be called. Otherwise, OCITransCommit() or OCITransAbort() must be called before releasing the connection back to the pool.
OraMTSSvcEnlist() enlists or de-enlists an OCI connection in a transaction coordinated by MS DTC.
DWORD OraMTSSvcEnlist(OCISvcCtx *OCISvc, OCIError *OCIErr, void *lpTrans, unsigned dwFlags );
Returns ORAMTSERR_NOERROR upon successful acquisition of an OCI connection.
OraMTSSvcEnlist() enlists two types of OCI connections:
With both connection types, your application must manually begin the MS-DTC-coordinated transaction.
For pooled OCI connections, the underlying object must be explicitly enlistable. When the transaction is complete, you must de-enlist OraMTSSvcEnlist(), passing NULL as the transaction pointer as follows:
OraMTSSvcEnlist(OCISvc, OCIenv, NULL, ORAMTS_ENFLG_DEFAULT)
If OraMTSSvcGet() is also involved in obtaining the connection, you must use OraMTSSvcRel() to release the connection when done.
Callers must:
For nonpooled OCI connections, the enlistment creates a context wrapper object within the resource dispenser. This has a transaction handle, error handle, and other information pertaining to the enlistment. The transaction handle must be undisturbed until the service context is finally disposed. Once a nonpooled OCI connection has been enlisted, it can be detached and attached to the underlying Oracle transaction through the same call using the dwFlags parameter. To detach from the Oracle transaction, set lpTrans to NULL and dwFlags to ORAMTS_ENFLG_DETCHTX. To resume the current transaction, lpTrans is not set to NULL and dwFlags is set to ORAMTS_ENFLG_RESUMTX.
OraMTSSvcEnlistEx() enlists an OCI connection or service context in an MS DTC transaction.
DWORD OraMTSSvcEnlistEx(OCISvcCtx *OCISvc, OCIError *OCIErr, void *lpTrans, unsigned dwFlags, char *lpDBName);
Returns ORAMTSERR_NOERROR on success.
This call is identical to OraMTSSvcEnlist() except for the addition of an lpDBName parameter. The lpDBName parameter is only used when enlisting nonpooled connections. The parameter is used to cache information to improve enlistment performance (regarding the Oracle Service for MTS for the Oracle8 database). This parameter is ignored for pooled connections and also for de-enlistment requests.
OraMTSTransTest() tests if you are running inside a Microsoft Transaction Server-initiated transaction.
BOOL OraMTSTransTest();
None.
Returns TRUE if running inside a Microsoft Transaction Server transaction. Otherwise, FALSE is returned.
This can be used by Microsoft Transaction Server transactional components to check if a component is executing within the context of a Microsoft Transaction Server transaction. Note that this call can only test Microsoft Transaction Server-initiated transactions. Transactions started by directly calling the MS DTC are not detected.
OraMTSOCIErrGet() retrieves the OCI error code and message text (if any) from the last OraMTSSvc operation (typically OraMTSSvcGet(), OraMTSSvcEnlist(), or OraMTSSvcEnlistEx()).
BOOL OraMTSOCIErrGet(DWORD *dwErr, LPTSTR lpcEMsg, DWORD *lpdLen);
Data Type | Parameter | Description |
---|---|---|
DWORD |
*dwErr |
(OUT) error code |
LPCHAR |
lpcEMsg |
(OUT) buffer for the error message if any |
DWORD |
*lpdLen |
(IN/OUT) size of lpcEmsg in; msg bytes out |
Returns TRUE if an OCI error was encountered. Otherwise, returns FALSE. If TRUE and lpcEMsg and lpdLen are valid, and there is a stashed error message, up to lpdLen bytes are copied into lpcEMsg. lpdLen is set to the actual number of message bytes.
This function retrieves the OCI error code and OCI error message text, if any, from the last OraMTSSvc operation on this thread. For example:
DWORD dwStat = OraMTSSvcGet("scott", "invalid_password","fin_prod", db",&mysvch, &myenvh, ORAMTS_CFLG_ALLDEFAULT); if (dwStat != ORAMTS_ERR_NOERROR) { DWORD dwOCIErr; char errBuf[MAX_PATH]; DWORD errBufLen = sizeof(effBuf); if (OraMTSOCIErrGet(&dwOCIErr, &errBuf, &errBufLen)) printf("OCIError %d: %s"\n); }
This section describes how to use ODBC with Microsoft Transaction Server and an Oracle8 database. Specific topics discussed are:
OCI connection pooling operates as described in section "Programming with Microsoft Transaction Server and an Oracle8 Database", with no changes to OCI code required for ODBC to operate.
To use Microsoft Transaction Server with either Oracle's ODBC Driver 8.1 or Microsoft's Oracle ODBC driver, you must set the connection attribute. Use the function SQLSetConnectAttr to call the parameter SQL_ATTR_ENLIST_IN_DTC in your ODBC code. This enables you to receive connection pooling and implicit transaction support. See "Setting Up MTS to Access Oracle" in the Microsoft Transaction Server online Help for instructions.
The ODBC Driver Manager distributed with ODBC 3.0 is a Resource Dispenser that supports connection pooling (see the Microsoft Transaction Server SDK for information). Oracle's ODBC driver release 8.1 integrates with the ODBC 3.0 Driver Manager by supporting the SQLSetConnectAttr(...,..., SQL_ATTR_ENLIST_IN_DTC) call to enlist/de-enlist the ODBC connection in/from MS DTC-coordinated transactions.
You must use release 8.1 of Oracle's ODBC driver. Previous versions do not work with Microsoft Transaction Server. Use Oracle's ODBC Driver 8.1 with:
To configure Oracle's ODBC Driver 8.1:
The Control Panel window appears.
The ODBC Data Source Administrator dialog box appears.
This deletes the configuration file that enables the Microsoft Transaction Server sample application demo to use Microsoft's ODBC driver.
The Create New Data Source wizard appears.
SERVER=DATABASE_ALIAS USERNAME=SCOTT PASSWORD=TIGER
If Using Oracle's ODBC For... | Then Enter... |
---|---|
Microsoft's sample application |
MTSSAMPLES.DSN (Microsoft's ODBC name). This name must exactly match the name you removed in substep 4b. |
Your own applications |
Any appropriate name. |
If the Oracle8 database version is 8.0.5 or earlier, you cannot use the integration described in this guide. However, there is a solution if you use Microsoft's Oracle ODBC driver. No other APIs are supported.
You can use Microsoft's Oracle ODBC Driver included in Windows NT Option Pack 4 to enable applications to interact with Microsoft Transaction Server and an Oracle8 database. If you use this driver, the rest of the information in this guide does not apply and you do not receive the performance benefits, other API support of Oracle integration, or Oracle 8.1 client support. See "Setting Up MTS to Access Oracle" in the Microsoft Transaction Server online Help for instructions on enabling Microsoft's Oracle ODBC Driver. After following those instructions, perform these additional steps:
To configure Microsoft's Oracle ODBC Driver:
ORAOCI = ORA73.DLL
There are no special requirements for using Oracle Objects for OLE. You must use version 8.1 of Oracle Objects for OLE. See the Oracle Objects for OLE online Help file for additional information on using Oracle Objects for OLE with Microsoft Transaction Server.
Connection pooling operates as described in section "Programming with Microsoft Transaction Server and an Oracle8 Database", with no changes required to the Oracle Objects for OLE code.
See the Oracle Provider for OLE DB User's Guide for information on using Oracle Provider for OLE DB with Microsoft Transaction Server.
Currently, other APIs are not supported, unless they use Oracle's ODBC Driver 8.1, such as ADO.
|
![]() Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
|