public IDbConnection Disconnect() { if (IsInActiveTransaction) { throw new InvalidOperationException("Disconnect cannot be called while a transaction is in progress."); } try { if (!ownConnection) { return(DisconnectSuppliedConnection()); } else { DisconnectOwnConnection(); ownConnection = false; return(null); } } finally { // Ensure that AfterTransactionCompletion gets called since // it takes care of the locks and cache. if (!IsInActiveTransaction) { // We don't know the state of the transaction session.AfterTransactionCompletion(false, null); } } }
void IEnlistmentNotification.Rollback(Enlistment enlistment) { using (new SessionIdLoggingContext(sessionImplementor.SessionId)) { sessionImplementor.AfterTransactionCompletion(false, null); logger.Debug("rolled back DTC transaction"); enlistment.Done(); IsInActiveTransaction = false; } }
void IEnlistmentNotification.InDoubt(Enlistment enlistment) { using (new SessionIdLoggingContext(session.SessionId)) { session.AfterTransactionCompletion(false, null); logger.Debug("DTC transaction is in doubt"); End(false); enlistment.Done(); IsInActiveTransaction = false; } }
/// <summary> /// Invoked after transaction commit/rollback. /// </summary> /// <param name="status"> /// Status according to <see cref="Spring.Transaction.Support.TransactionSynchronizationStatus"/> /// </param> /// <remarks> /// Can e.g. perform resource cleanup, in this case after transaction completion. /// <p> /// Note that exceptions will get propagated to the commit or rollback /// caller, although they will not influence the outcome of the transaction. /// </p> /// </remarks> public override void AfterCompletion(TransactionSynchronizationStatus status) { if (!newSession) { ISession session = sessionHolder.Session; // Provide correct transaction status for releasing the Session's cache locks, // if possible. Else, closing will release all cache locks assuming a rollback. ISessionImplementor sessionImplementor = session as ISessionImplementor; if (sessionImplementor != null) { sessionImplementor.AfterTransactionCompletion(status == TransactionSynchronizationStatus.Committed, sessionHolder.Transaction); } if (newSession) { SessionFactoryUtils.CloseSessionOrRegisterDeferredClose(session, sessionFactory); } } if (!newSession && status != TransactionSynchronizationStatus.Committed) { // Clear all pending inserts/updates/deletes in the Session. // Necessary for pre-bound Sessions, to avoid inconsistent state. sessionHolder.Session.Clear(); } if (this.sessionHolder.DoesNotHoldNonDefaultSession) { sessionHolder.SynchronizedWithTransaction = false; } }
public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session) { if (session.TransactionContext != null) return; if (System.Transactions.Transaction.Current == null) return; var transactionContext = new DistributedTransactionContext(session, System.Transactions.Transaction.Current); session.TransactionContext = transactionContext; logger.DebugFormat("enlisted into DTC transaction: {0}", transactionContext.AmbientTransation.IsolationLevel); session.AfterTransactionBegin(null); transactionContext.AmbientTransation.TransactionCompleted += delegate(object sender, TransactionEventArgs e) { bool wasSuccessful = false; try { wasSuccessful = e.Transaction.TransactionInformation.Status == TransactionStatus.Committed; } catch (ObjectDisposedException ode) { logger.Warn("Completed transaction was disposed, assuming transaction rollback", ode); } session.AfterTransactionCompletion(wasSuccessful, null); if (transactionContext.ShouldCloseSessionOnDistributedTransactionCompleted) { session.CloseSessionFromDistributedTransaction(); } session.TransactionContext = null; }; transactionContext.AmbientTransation.EnlistVolatile(transactionContext, EnlistmentOptions.EnlistDuringPrepareRequired); }
public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session) { if (session.TransactionContext != null) { return; } if (System.Transactions.Transaction.Current == null) { return; } var transactionContext = new DistributedTransactionContext(session, System.Transactions.Transaction.Current); session.TransactionContext = transactionContext; logger.DebugFormat("enlisted into DTC transaction: {0}", transactionContext.AmbientTransation.IsolationLevel); session.AfterTransactionBegin(null); //use pull-request https://github.com/nhibernate/nhibernate-core/pull/206 (with handler manipulation) TransactionCompletedEventHandler handler = null; handler = delegate(object sender, TransactionEventArgs e) { lock (session) { using (new SessionIdLoggingContext(session.SessionId)) { ((DistributedTransactionContext)session.TransactionContext).IsInActiveTransaction = false; bool wasSuccessful = false; try { wasSuccessful = e.Transaction.TransactionInformation.Status == TransactionStatus.Committed; } catch (ObjectDisposedException ode) { logger.Warn("Completed transaction was disposed, assuming transaction rollback", ode); } session.AfterTransactionCompletion(wasSuccessful, null); if (transactionContext.ShouldCloseSessionOnDistributedTransactionCompleted) { session.CloseSessionFromDistributedTransaction(); } session.TransactionContext = null; } transactionContext.AmbientTransation.TransactionCompleted -= handler; } }; transactionContext.AmbientTransation.TransactionCompleted += handler; transactionContext.AmbientTransation.EnlistVolatile(transactionContext, EnlistmentOptions.EnlistDuringPrepareRequired); }
/// <summary> /// Handle the transaction completion. Notify <see cref="ConnectionManager"/> of the end of the /// transaction. Notify end of transaction to the session and to <see cref="ConnectionManager.DependentSessions"/> /// if any. Close sessions requiring it then cleanup transaction contextes and then <see cref="Unlock"/> blocked /// threads. /// </summary> /// <param name="isCommitted"><see langword="true"/> if the transaction is committed, <see langword="false"/> /// otherwise.</param> protected virtual void CompleteTransaction(bool isCommitted) { // Some implementations (Mono) may "re-complete" the transaction on the cloned transaction disposal: // do an early exit here in such case. if (!IsInActiveTransaction) { return; } try { // Allow transaction completed actions to run while others stay blocked. _bypassLock.Value = true; using (_session.BeginContext()) { // Flag active as false before running actions, otherwise the session may not cleanup as much // as possible. IsInActiveTransaction = false; // Never allows using connection on after transaction event. And tell the connection manager // it is called from system transaction. Allows releasing of connection on next usage // when release mode is on commit, allows un-enlisting the connection on next usage // when release mode is on close. Without BeginsProcessingFromSystemTransaction(false), // the connection manager would attempt those operations immediately, causing concurrency // issues and crashes for some data providers. using (_session.ConnectionManager.BeginProcessingFromSystemTransaction(false)) { _session.ConnectionManager.AfterTransaction(); // Required for un-enlisting the connection manager when auto-join is false. // Not done in AfterTransaction, because users may use NHibernate transactions // within scopes, although mixing is not advised. if (!ShouldCloseSessionOnSystemTransactionCompleted) { _session.ConnectionManager.EnlistIfRequired(null); } _session.AfterTransactionCompletion(isCommitted, null); foreach (var dependentSession in _session.ConnectionManager.DependentSessions) { dependentSession.AfterTransactionCompletion(isCommitted, null); } Cleanup(_session); } } } catch (Exception ex) { // May be run in a dedicated thread. Log any error, otherwise they could stay unlogged. _logger.Error(ex, "Failure at transaction completion"); throw; } finally { // Dispose releases blocked threads by the way. Dispose(); } }
private void AfterTransactionCompletion(bool successful) { using (new SessionIdLoggingContext(sessionId)) { session.AfterTransactionCompletion(successful, this); NotifyLocalSynchsAfterTransactionCompletion(successful); session = null; begun = false; } }
private void AfterTransactionCompletion(bool successful) { session.ConnectionManager.AfterTransaction(); session.AfterTransactionCompletion(successful, this); NotifyLocalSynchsAfterTransactionCompletion(successful); foreach (var dependentSession in session.ConnectionManager.DependentSessions) { dependentSession.AfterTransactionCompletion(successful, this); } session = null; begun = false; }
void IEnlistmentNotification.InDoubt(Enlistment enlistment) { using (new SessionIdLoggingContext(sessionImplementor.SessionId)) { sessionImplementor.ConnectionManager.AfterTransaction(); sessionImplementor.AfterTransactionCompletion(false, null); foreach (var dependentSession in sessionImplementor.ConnectionManager.DependentSessions) { dependentSession.AfterTransactionCompletion(false, null); } logger.Debug("DTC transaction is in doubt"); enlistment.Done(); IsInActiveTransaction = false; } }
public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session) { if (session.TransactionContext != null) { return; } if (System.Transactions.Transaction.Current == null) { return; } var transactionContext = new DistributedTransactionContext(session, System.Transactions.Transaction.Current); session.TransactionContext = transactionContext; logger.DebugFormat("enlisted into DTC transaction: {0}", transactionContext.AmbientTransation.IsolationLevel); session.AfterTransactionBegin(null); transactionContext.AmbientTransation.TransactionCompleted += delegate(object sender, TransactionEventArgs e) { using (new SessionIdLoggingContext(session.SessionId)) { bool wasSuccessful = false; try { wasSuccessful = e.Transaction.TransactionInformation.Status == TransactionStatus.Committed; } catch (ObjectDisposedException ode) { logger.Warn("Completed transaction was disposed, assuming transaction rollback", ode); } session.AfterTransactionCompletion(wasSuccessful, null); if (transactionContext.ShouldCloseSessionOnDistributedTransactionCompleted) { session.CloseSessionFromDistributedTransaction(); } session.TransactionContext = null; } }; transactionContext.AmbientTransation.EnlistVolatile(transactionContext, EnlistmentOptions.EnlistDuringPrepareRequired); }
public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session) { if (session.TransactionContext != null) { return; } if (System.Transactions.Transaction.Current == null) { return; } var originatingSession = session.ConnectionManager.Session; if (originatingSession != session) { session.TransactionContext = new DependentContext(); } if (originatingSession.TransactionContext != null) { return; } session = originatingSession; var transactionContext = new DistributedTransactionContext(session, System.Transactions.Transaction.Current); session.TransactionContext = transactionContext; logger.DebugFormat("enlisted into DTC transaction: {0}", transactionContext.AmbientTransation.IsolationLevel); session.AfterTransactionBegin(null); foreach (var dependentSession in session.ConnectionManager.DependentSessions) { dependentSession.AfterTransactionBegin(null); } TransactionCompletedEventHandler handler = null; handler = delegate(object sender, TransactionEventArgs e) { using (new SessionIdLoggingContext(session.SessionId)) { ((DistributedTransactionContext)session.TransactionContext).IsInActiveTransaction = false; bool wasSuccessful = false; try { wasSuccessful = e.Transaction.TransactionInformation.Status == TransactionStatus.Committed; } catch (ObjectDisposedException ode) { logger.Warn("Completed transaction was disposed, assuming transaction rollback", ode); } session.ConnectionManager.AfterTransaction(); session.AfterTransactionCompletion(wasSuccessful, null); foreach (var dependentSession in session.ConnectionManager.DependentSessions) { dependentSession.AfterTransactionCompletion(wasSuccessful, null); } Cleanup(session); } e.Transaction.TransactionCompleted -= handler; }; transactionContext.AmbientTransation.TransactionCompleted += handler; transactionContext.AmbientTransation.EnlistVolatile(transactionContext, EnlistmentOptions.EnlistDuringPrepareRequired); }
private void AfterTransactionCompletion(bool successful) { session.AfterTransactionCompletion(successful, this); session = null; begun = false; }
public void AfterTransactionCompletion(bool successful, ITransaction tx) { _session.AfterTransactionCompletion(successful, tx); }
private void AfterTransactionCompletion(bool successful) { session.AfterTransactionCompletion(successful); session = null; }
public void afterTransactionCompletion(bool successful, ITransaction tx) { delegat.AfterTransactionCompletion(successful, tx); }