/// <summary> /// Rolls back the current transaction. /// </summary> /// <exception cref="TransactionException">Thrown if the stack is empty.</exception> internal void Rollback() { Transaction transaction; using (TimedLock.Lock(syncLock)) { if (base.Count == 0) { throw new TransactionException(EmptyMsg); } transaction = base.Pop(); if (base.Count == 0) { manager.Trace(0, "Begin rollback BASE", "ID=" + id.ToString()); } else { manager.Trace(0, string.Format("Begin rollback NESTED [{0}]", base.Count), "ID=" + id.ToString()); } // Submit the operations being undone back to the // resource in the reverse order that they were // originally performed. ITransactedResource resource = manager.Resource; UpdateContext context = new UpdateContext(manager, false, false, true, ID); List <ILogPosition> positions; positions = operationLog.GetPositionsTo(transaction.Position); if (resource.BeginUndo(context)) { for (int i = 0; i < positions.Count; i++) { var operation = operationLog.Read(manager.Resource, positions[i]); manager.Trace(0, "Undo: " + operation.Description, "ID=" + id.ToString()); resource.Undo(context, operation); } } resource.EndUndo(context); if (base.Count == 0) { manager.EndTransaction(this); manager.Trace(0, "End rollback BASE", "ID=" + id.ToString()); } else { operationLog.Truncate(transaction.Position); manager.Trace(0, string.Format("End rollback NESTED [{0}]", base.Count), "ID=" + id.ToString()); } } }