public AmbientScopeSuppressor()
            {
                _savedScope = PersistenceScopeImpl.GetAmbientScope();

                // We're hiding the ambient scope but not removing its instance
                // altogether. This is to be tolerant to some programming errors.
                //
                // Suppose we removed the ambient scope instance here. If someone
                // was to start a parallel task without suppressing
                // the ambient context and then tried to suppress the ambient
                // context within the parallel task while the original flow
                // of execution was still ongoing (a strange thing to do, I know,
                // but I'm sure this is going to happen), we would end up
                // removing the ambient context instance of the original flow
                // of execution from within the parallel flow of execution!
                //
                // As a result, any code in the original flow of execution
                // that would attempt to access the ambient scope would end up
                // with a null value since we removed the instance.
                //
                // It would be a fairly nasty bug to track down. So don't let
                // that happen. Hiding the ambient scope (i.e. clearing the CallContext
                // in our execution flow but leaving the ambient scope instance untouched)
                // is safe.
                PersistenceScopeImpl.HideAmbientUnitOfWork();
            }
            public PersistenceScopeImpl(
                IPersistenceContextFactory persistenceContextFactory,
                PersistenceUnitOfWorkOption joiningOption,
                bool readOnly,
                IsolationLevel?isolationLevel)
            {
                _persistenceContextFactory = persistenceContextFactory;
                if (isolationLevel.HasValue &&
                    joiningOption == PersistenceUnitOfWorkOption.JoinExisting)
                {
                    throw new ArgumentException(
                              @"Cannot join an ambient persistence scope when an explicit database transaction is required. 
When requiring explicit database transactions to be used (i.e. when the 'isolationLevel' parameter is set), 
you must not also ask to join the ambient scope (i.e. the 'joinAmbient' parameter must be set to false).");
                }

                _disposed    = false;
                _completed   = false;
                _readOnly    = readOnly;
                _parentScope = GetAmbientScope();

                if (_parentScope != null && joiningOption == PersistenceUnitOfWorkOption.JoinExisting)
                {
                    if (_parentScope._readOnly && !this._readOnly)
                    {
                        throw new InvalidOperationException("Cannot nest a read/write Scope within a read-only Scope.");
                    }
                    _nested             = true;
                    _persistenceContext = _parentScope._persistenceContext;

                    if (_persistenceContext as IPersistenceContextExplicit == null)
                    {
                        throw new InvalidProgramException($"Parent PersistenceContext does not implement {typeof(IPersistenceContextExplicit).Name}");
                    }
                }
                else
                {
                    _nested             = false;
                    _persistenceContext = _persistenceContextFactory.Create();

                    var explicitContext = _persistenceContext as IPersistenceContextExplicit;
                    if (explicitContext == null)
                    {
                        throw new InvalidProgramException($"PersistenceContext does not implement {typeof(IPersistenceContextExplicit).Name}");
                    }

                    if (isolationLevel.HasValue)
                    {
                        _persistenceTransaction = explicitContext.BeginTransaction(isolationLevel.Value);
                    }
                }
                SetAmbientScope(this);
            }
            public void Dispose()
            {
                if (_disposed)
                {
                    return;
                }

                if (_savedScope != null)
                {
                    PersistenceScopeImpl.SetAmbientScope(_savedScope);
                    _savedScope = null;
                }

                _disposed = true;
            }
            /// <summary>
            /// Makes the provided 'PersistenceContextScope' available as the the ambient scope via the CallContext.
            /// </summary>
            internal static void SetAmbientScope(PersistenceScopeImpl newScope)
            {
                if (newScope == null)
                {
                    throw new ArgumentNullException("newAmbientScope");
                }

                var current = CallContext.LogicalGetData(AmbientScopeKey) as InstanceIdentifier;

                if (current == newScope._instanceIdentifier)
                {
                    return;
                }

                // Store the new scope's instance identifier in the CallContext, making it the ambient scope
                CallContext.LogicalSetData(AmbientScopeKey, newScope._instanceIdentifier);

                // Keep track of this instance (or do nothing if we're already tracking it)
                ScopeInstances.GetValue(newScope._instanceIdentifier, key => newScope);
            }