// this chains some try/finally blocks to // - complete and dispose the scoped filesystems // - deal with events if appropriate // - remove the scope context if it belongs to this scope // - deal with detachable scopes // here, // - completed indicates whether the scope has been completed // can be true or false, but in both cases the scope is exiting // in a normal way // - onException indicates whether completing/aborting the database // transaction threw an exception, in which case 'completed' has // to be false + events don't trigger and we just to some cleanup // to ensure we don't leave a scope around, etc private void RobustExit(bool completed, bool onException) { if (onException) { completed = false; } TryFinally(() => { if (_scopeFileSystem == true) { if (completed) { _fscope.Complete(); } _fscope.Dispose(); _fscope = null; } }, () => { // deal with events if (onException == false && _eventDispatcher != null) { _eventDispatcher.ScopeExit(completed); } }, () => { // if *we* created it, then get rid of it if (_scopeProvider.AmbientContext == _scopeContext) { try { _scopeProvider.AmbientContext.ScopeExit(completed); } finally { // removes the ambient context (ambient scope already gone) _scopeProvider.SetAmbient(null); } } }, () => { if (Detachable) { // get out of the way, restore original _scopeProvider.SetAmbient(OrigScope, OrigContext); Attached = false; OrigScope = null; OrigContext = null; } }); }
public void Dispose() { EnsureNotDisposed(); if (this != _scopeProvider.AmbientScope) { throw new InvalidOperationException("Not the ambient scope."); } #if DEBUG_SCOPES _scopeProvider.Disposed(this); #endif if (_database != null) { _database.Dispose(); } _scopeProvider.SetAmbient(null); _disposed = true; GC.SuppressFinalize(this); }