| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- //------------------------------------------------------------------------------
- // <copyright file="OdbcTransaction.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- //------------------------------------------------------------------------------
- using System;
- using System.Data;
- using System.Data.Common;
- using System.Threading;
- namespace System.Data.Odbc
- {
- public sealed class OdbcTransaction : DbTransaction {
- private OdbcConnection _connection;
- private IsolationLevel _isolevel = IsolationLevel.Unspecified;
- private OdbcConnectionHandle _handle;
- internal OdbcTransaction(OdbcConnection connection, IsolationLevel isolevel, OdbcConnectionHandle handle) {
- OdbcConnection.VerifyExecutePermission();
-
- _connection = connection;
- _isolevel = isolevel;
- _handle = handle;
- }
- new public OdbcConnection Connection { // MDAC 66655
- get {
- return _connection;
- }
- }
- override protected DbConnection DbConnection { // MDAC 66655
- get {
- return Connection;
- }
- }
- override public IsolationLevel IsolationLevel {
- get {
- OdbcConnection connection = _connection;
- if (null == connection ) {
- throw ADP.TransactionZombied(this);
- }
- //We need to query for the case where the user didn't set the isolevel
- //BeginTransaction(), but we should also query to see if the driver
- //"rolled" the level to a higher supported one...
- if(IsolationLevel.Unspecified == _isolevel) {
- //Get the isolation level
- int sql_iso= connection .GetConnectAttr(ODBC32.SQL_ATTR.TXN_ISOLATION, ODBC32.HANDLER.THROW);
- switch((ODBC32.SQL_TRANSACTION)sql_iso) {
- case ODBC32.SQL_TRANSACTION.READ_UNCOMMITTED:
- _isolevel = IsolationLevel.ReadUncommitted;
- break;
- case ODBC32.SQL_TRANSACTION.READ_COMMITTED:
- _isolevel = IsolationLevel.ReadCommitted;
- break;
- case ODBC32.SQL_TRANSACTION.REPEATABLE_READ:
- _isolevel = IsolationLevel.RepeatableRead;
- break;
- case ODBC32.SQL_TRANSACTION.SERIALIZABLE:
- _isolevel = IsolationLevel.Serializable;
- break;
- case ODBC32.SQL_TRANSACTION.SNAPSHOT:
- _isolevel = IsolationLevel.Snapshot;
- break;
- default:
- throw ODBC.NoMappingForSqlTransactionLevel(sql_iso);
- };
- }
- return _isolevel;
- }
- }
- override public void Commit() {
- OdbcConnection.ExecutePermission.Demand(); // MDAC 81476
- OdbcConnection connection = _connection;
- if (null == connection) {
- throw ADP.TransactionZombied(this);
- }
- connection.CheckState(ADP.CommitTransaction); // MDAC 68289
- //Note: SQLEndTran success if not actually in a transaction, so we have to throw
- //since the IDbTransaciton spec indicates this is an error for the managed packages
- if(null == _handle) {
- throw ODBC.NotInTransaction();
- }
-
- ODBC32.RetCode retcode = _handle.CompleteTransaction(ODBC32.SQL_COMMIT);
- if (retcode == ODBC32.RetCode.ERROR) {
- //If an error has occurred, we will throw an exception in HandleError,
- //and leave the transaction active for the user to retry
- connection.HandleError(_handle, retcode);
- }
- //Transaction is complete...
- connection.LocalTransaction = null;
- _connection = null;
- _handle = null;
-
- }
- protected override void Dispose(bool disposing) {
- if (disposing) {
- OdbcConnectionHandle handle = _handle;
- _handle = null;
- if (null != handle){
- try{
- ODBC32.RetCode retcode = handle.CompleteTransaction(ODBC32.SQL_ROLLBACK);
- if (retcode == ODBC32.RetCode.ERROR) {
- //don't throw an exception here, but trace it so it can be logged
- if (_connection != null) {
- Exception e = _connection.HandleErrorNoThrow(handle, retcode);
- ADP.TraceExceptionWithoutRethrow(e);
- }
- }
- }
- catch (Exception e){
- //
- if (!ADP.IsCatchableExceptionType(e)) {
- throw;
- }
- }
- }
- if (_connection != null) {
- if (_connection.IsOpen) {
- _connection.LocalTransaction = null;
- }
- }
- _connection = null;
- _isolevel = IsolationLevel.Unspecified;
- }
- base.Dispose(disposing);
- }
- override public void Rollback() {
- OdbcConnection connection = _connection;
- if (null == connection) {
- throw ADP.TransactionZombied(this);
- }
- connection.CheckState(ADP.RollbackTransaction); // MDAC 68289
- //Note: SQLEndTran success if not actually in a transaction, so we have to throw
- //since the IDbTransaciton spec indicates this is an error for the managed packages
- if(null == _handle) {
- throw ODBC.NotInTransaction();
- }
- ODBC32.RetCode retcode = _handle.CompleteTransaction(ODBC32.SQL_ROLLBACK);
- if (retcode == ODBC32.RetCode.ERROR) {
- //If an error has occurred, we will throw an exception in HandleError,
- //and leave the transaction active for the user to retry
- connection.HandleError(_handle, retcode);
- }
- connection.LocalTransaction = null;
- _connection = null;
- _handle = null;
- }
- }
- }
|