/// <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); } }
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); } }
protected sealed override IList <TItem> GetNextBatch(int batchSize) { using (var scope = new PersistenceScope(PersistenceContextType.Read)) { var items = GetNextEntityBatch(batchSize); scope.Complete(); return(items); } }
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); } }
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(); } }