public override void EnlistTransaction(Transaction systemTransaction) { lock (m_syncRoot) { CheckClosed(); if (systemTransaction == null) { throw new ArgumentNullException("transaction"); } HsqlEnlistment enlistment = m_enlistment; if (enlistment == null) { enlistment = new HsqlEnlistment(this, systemTransaction); if (!systemTransaction.EnlistPromotableSinglePhase(enlistment)) { if (m_transaction == null) { BeginTransaction(HsqlConvert.ToIsolationLevel(systemTransaction.IsolationLevel)); } enlistment.m_dbTransaction = m_transaction; systemTransaction.EnlistDurable(enlistment.Rmid, enlistment, EnlistmentOptions.None); } m_enlistment = enlistment; GC.KeepAlive(this); } else if (enlistment.Transaction != systemTransaction) { throw new InvalidOperationException( "Connection currently has transaction enlisted." + " Finish current transaction and retry."); // NOI18N } } }
/// <summary> /// Closes this connection. /// </summary> internal void CloseInternal() { ConnectionState state = m_connectionState; if (state == ConnectionState.Closed) { return; } HsqlSession session = m_session; if (m_session == null) { // Sanity-Check: Should never happen. throw new InvalidOperationException( "HsqlSession is null"); // NOI18N } // Handle dispose/close while enlisted in a system transaction. HsqlTransaction transaction = m_transaction; HsqlEnlistment enlistment = m_enlistment; bool enlisted = (enlistment != null); bool preserveEnlistment = (enlisted && !enlistment.m_disposeConnection); if (preserveEnlistment) { #if DEBUG // Without this, it is difficult to debug // because the m_enlistment's connection // ceases to be this one and this connection // loses its reference to the enlistment // (m_enlistment is set null below). m_enlistment_dbg = m_enlistment; #endif // ...then until it ceases to participate in a // System.Transactions.Transaction, the enlistment // needs a valid local transaction to commit or // rollback HsqlConnection connection = new HsqlConnection(this); connection.m_connectionState = ConnectionState.Open; connection.m_session = session; connection.m_enlistment = enlistment; connection.m_transaction = transaction; enlistment.m_dbConnection = connection; enlistment.m_disposeConnection = true; if (transaction != null) { transaction.m_connection = connection; } } SetStateInternal(ConnectionState.Closed); m_session = null; m_transaction = null; m_enlistment = null; m_dbMetaData = null; m_settings = null; if (!enlisted) { // No need to roll back here. This will happen automatically // a moment later on the back end in response to the // session.Close() call below. if (transaction != null) { transaction.DisposeInternal(/*rollback*/ false); } // release the back-end session and any associated resources, // such as network sockets, etc. session.Close(); } }