Beispiel #1
0
        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();
            }
        }