private void InternalDispose() { // Set this if it is called internally. _disposed = true; try { PopScope(); TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (null == _expectedCurrent) { if (etwLog.IsEnabled()) { etwLog.TransactionScopeDisposed(TransactionTraceIdentifier.Empty); } } else { if (etwLog.IsEnabled()) { etwLog.TransactionScopeDisposed(_expectedCurrent.TransactionTraceId); } } // If Transaction.Current is not null, we have work to do. Otherwise, we don't, except to replace // the previous value. if (null != _expectedCurrent) { if (!_complete) { if (etwLog.IsEnabled()) { etwLog.TransactionScopeIncomplete(_expectedCurrent.TransactionTraceId); } // // Note: Rollback is not called on expected current because someone could conceiveably // dispose expectedCurrent out from under the transaction scope. // Transaction rollbackTransaction = _committableTransaction; if (rollbackTransaction == null) { rollbackTransaction = _dependentTransaction; } Debug.Assert(rollbackTransaction != null); rollbackTransaction.Rollback(); } else { // If we are supposed to commit on dispose, cast to CommittableTransaction and commit it. if (null != _committableTransaction) { _committableTransaction.Commit(); } else { Debug.Assert(null != _dependentTransaction, "null != this.dependentTransaction"); _dependentTransaction.Complete(); } } } } finally { if (null != _scopeTimer) { _scopeTimer.Dispose(); } if (null != _committableTransaction) { _committableTransaction.Dispose(); // If we created the committable transaction then we placed a clone in expectedCurrent // and it needs to be disposed as well. _expectedCurrent.Dispose(); } if (null != _dependentTransaction) { _dependentTransaction.Dispose(); } } }