/// <summary>
        /// Adds an <see cref="ExceptionLogEntry"/>.  If the <see cref="ExceptionLogEntry"/> cannot be created, the error is logged to the log file instead.
        /// </summary>
        /// <param name="operationName"></param>
        /// <param name="e"></param>
        public static void Log(string operationName, Exception e)
        {
            try
            {
                // log the error to the database
                using (PersistenceScope scope = new PersistenceScope(PersistenceContextType.Update, PersistenceScopeOption.RequiresNew))
                {
                    // disable change-set auditing for this context
                    ((IUpdateContext)PersistenceScope.CurrentContext).ChangeSetRecorder = null;

                    DefaultExceptionRecorder recorder = new DefaultExceptionRecorder();
                    ExceptionLogEntry        logEntry = recorder.CreateLogEntry(operationName, e);

                    PersistenceScope.CurrentContext.Lock(logEntry, DirtyState.New);

                    scope.Complete();
                }
            }
            catch (Exception x)
            {
                // if we fail to properly log the exception, there is nothing we can do about it
                // just log a message to the log file
                Platform.Log(LogLevel.Error, x);

                // also log the original exception to the log file, since it did not get logged to the DB
                Platform.Log(LogLevel.Error, e);
            }
        }
Exemplo n.º 2
0
        protected sealed override bool ClaimItem(TItem item)
        {
            try
            {
                using (var scope = new PersistenceScope(PersistenceContextType.Update))
                {
                    var context = (IUpdateContext)PersistenceScope.CurrentContext;
                    context.ChangeSetRecorder.OperationName = this.GetType().FullName;

                    // need to lock the item in context, to allow loading of extended properties collection by subclass
                    context.Lock(item);

                    // mark item as being in process
                    MarkItemClaimed(item);

                    // complete the transaction
                    scope.Complete();
                }
                return(true);
            }
            catch (EntityVersionException)
            {
                // if we get a version exception, the item has already been claimed by another process
                // this is not an error
                return(false);
            }
        }
Exemplo n.º 3
0
        protected sealed override IList <TItem> GetNextBatch(int batchSize)
        {
            using (var scope = new PersistenceScope(PersistenceContextType.Read))
            {
                var items = GetNextEntityBatch(batchSize);

                scope.Complete();
                return(items);
            }
        }
Exemplo n.º 4
0
        protected sealed override void ProcessItem(TItem item)
        {
            Exception error = null;

            using (var scope = new PersistenceScope(PersistenceContextType.Update))
            {
                var context = (IUpdateContext)PersistenceScope.CurrentContext;
                context.ChangeSetRecorder.OperationName = this.GetType().FullName;

                // need to lock the item in context, to allow loading of extended properties collection by subclass
                context.Lock(item);

                try
                {
                    // take action based on item
                    ActOnItem(item);

                    // ensure that the commit will ultimately succeed
                    context.SynchState();

                    // success callback
                    OnItemSucceeded(item);

                    // complete the transaction
                    scope.Complete();
                }
                catch (Exception e)
                {
                    // one of the actions failed
                    Platform.Log(LogLevel.Error, e);
                    error = e;
                }
            }

            // exceptions thrown upon exiting the using block above are intentionally not caught here,
            // allow them to be caught by the calling method

            // post-processing
            if (error == null)
            {
                AfterCommit(item);
            }
            else
            {
                UpdateItemOnError(item, error);
            }
        }
Exemplo n.º 5
0
        private void UpdateItemOnError(TItem item, Exception error)
        {
            // use a new scope to mark the item as failed, because we don't want to commit any changes made in the outer scope
            using (var scope = new PersistenceScope(PersistenceContextType.Update, PersistenceScopeOption.RequiresNew))
            {
                var failContext = (IUpdateContext)PersistenceScope.CurrentContext;
                failContext.ChangeSetRecorder.OperationName = this.GetType().FullName;

                // bug #7191 : Reload the TItem in this scope;  using the existing item results in NHibernate throwing a lazy loading exception
                var itemForThisScope = failContext.Load <TItem>(item.GetRef(), EntityLoadFlags.None);

                // lock item into this context
                failContext.Lock(itemForThisScope);

                // failure callback
                OnItemFailed(itemForThisScope, error);

                // complete the transaction
                scope.Complete();
            }
        }
        /// <summary>
        /// Disposes of this scope.
        /// </summary>
        /// <remarks>
        /// If this scope is associated with an update context and is the owner of that context,
        /// then disposal will commit or rollback the changes made in the update context, depending
        /// on whether this scope was marked Completed.  If <see cref="Complete"/> was called on this scope,
        /// then disposal will attempt to commit the update context, otherwise it will simply dispose it,
        /// which is effectively a rollback.
        /// </remarks>
        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;

                if (this != _head)
                {
                    throw new InvalidOperationException("Disposed out of order.");
                }

                try
                {
                    if (OwnsContext)
                    {
                        CloseContext();
                    }
                    else
                    {
                        // if the vote is still "undecided", treat it as an abort
                        if (_vote == Vote.Undecided)
                        {
                            _vote = Vote.Abort;

                            // we have an inherited context, so we need to propagate "aborts" up to the parent
                            _parent._vote = Vote.Abort;
                        }
                    }
                }
                finally
                {
                    // if CloseContext fails, we are still disposing of this scope, so we set the head
                    // to point to the parent
                    _head = _parent;
                }
            }
        }
 /// <summary>
 /// Creates a new persistence scope for the specified context.  The scope assumes ownership of the context
 /// and closes it when the scope terminates.
 /// </summary>
 /// <param name="context"></param>
 public PersistenceScope(IPersistenceContext context)
 {
     _context = context;
     _parent  = _head;
     _head    = this;
 }