// If the transaction has aborted then we switch over to a new transaction // which we will immediately abort after setting Transaction.Current public static TransactionScope CreateTransactionScope(Transaction transaction) { try { return transaction == null ? null : new TransactionScope(transaction); } catch (TransactionAbortedException) { CommittableTransaction tempTransaction = new CommittableTransaction(); try { return new TransactionScope(tempTransaction.Clone()); } finally { tempTransaction.Rollback(); } } }
public void ProcessData(int employeeId) { // There is not much processing logic here... // We are assuming that the organization has 50 employees with sequential Employee Ids // If the employeeId > 50, we are sending an Http Status code of 500 (Internal Server Error) back to the client // else, we assume that the processing is successful and send an Http Status code of 200 (Successfull) ReceiveContext receiveContext; if (!ReceiveContext.TryGet(OperationContext.Current.IncomingMessageProperties, out receiveContext)) { Console.WriteLine("ReceiveContext property was not found in the message..."); return; } if (employeeId > 50) { // Abandon receiveContext.Abandon(TimeSpan.MaxValue); } else { // Complete in Transaction block. CommittableTransaction committableTransaction = new CommittableTransaction(); Transaction.Current = committableTransaction; try { receiveContext.Complete(TimeSpan.MaxValue); committableTransaction.Commit(); } catch { committableTransaction.Rollback(); // If the transaction was not completed we call Abandon explicitly which sends an Http 500 to the client receiveContext.Abandon(TimeSpan.MaxValue); } } }
private void EmployWorkersForJob(RunningJob runningJob) { foreach (JobSection jobSection in runningJob.Sections) { if (null == jobSection.WorkerCard) continue; // We don't have workers for this role uint availableWorkers = jobSection.WorkerCard.MaxNumOfInstances - GetWorkingWorkersNumber(jobSection.RoleType); if (availableWorkers == 0) continue; // All available workers for that role are busy // Try to hire ONE worker for the role. // We should not hire more than one worker for the role in one iteration to give other WorkerManagers a chance to take some workload. RoleSlotToken roleSlotToken = null; var transaction = new CommittableTransaction(TransactionManager.MaximumTimeout); Transaction oldAmbient = Transaction.Current; Transaction.Current = transaction; try { roleSlotToken = jobSection.GetFreeSlot(); } finally { Transaction.Current = oldAmbient; if (null == roleSlotToken) { transaction.Rollback(); transaction.Dispose(); } } if (null == roleSlotToken) { continue; } WorkAssignment workAssignment = new WorkAssignment(jobSection.WorkRequest, roleSlotToken, runningJob.JobId, runningJob.ScheduleRunDuration, runningJob.ScheduleCreatedBy, runningJob.NotificationId, runningJob.Frequency); EmployWorker(jobSection.WorkerCard, workAssignment, transaction); jobSection.WorkerIDs.Add(workAssignment.WorkerId); } }
public void Dispose() { bool flag = false; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), "TransactionScope.Dispose"); } if (this.disposed) { if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), "TransactionScope.Dispose"); } } else { if (this.scopeThread != Thread.CurrentThread) { if (DiagnosticTrace.Error) { InvalidOperationExceptionTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), System.Transactions.SR.GetString("InvalidScopeThread")); } throw new InvalidOperationException(System.Transactions.SR.GetString("InvalidScopeThread")); } Exception exception = null; try { this.disposed = true; TransactionScope currentScope = this.threadContextData.CurrentScope; Transaction contextTransaction = null; Transaction transaction = Transaction.FastGetTransaction(currentScope, this.threadContextData, out contextTransaction); if (!this.Equals(currentScope)) { if (currentScope == null) { Transaction committableTransaction = this.committableTransaction; if (committableTransaction == null) { committableTransaction = this.dependentTransaction; } committableTransaction.Rollback(); flag = true; throw TransactionException.CreateInvalidOperationException(System.Transactions.SR.GetString("TraceSourceBase"), System.Transactions.SR.GetString("TransactionScopeInvalidNesting"), null); } if ((currentScope.interopOption == EnterpriseServicesInteropOption.None) && (((null != currentScope.expectedCurrent) && !currentScope.expectedCurrent.Equals(transaction)) || ((null != transaction) && (null == currentScope.expectedCurrent)))) { if (DiagnosticTrace.Warning) { TransactionTraceIdentifier transactionTraceId; TransactionTraceIdentifier empty; if (null == transaction) { empty = TransactionTraceIdentifier.Empty; } else { empty = transaction.TransactionTraceId; } if (null == this.expectedCurrent) { transactionTraceId = TransactionTraceIdentifier.Empty; } else { transactionTraceId = this.expectedCurrent.TransactionTraceId; } TransactionScopeCurrentChangedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), transactionTraceId, empty); } exception = TransactionException.CreateInvalidOperationException(System.Transactions.SR.GetString("TraceSourceBase"), System.Transactions.SR.GetString("TransactionScopeIncorrectCurrent"), null); if (null != transaction) { try { transaction.Rollback(); } catch (TransactionException) { } catch (ObjectDisposedException) { } } } while (!this.Equals(currentScope)) { if (exception == null) { exception = TransactionException.CreateInvalidOperationException(System.Transactions.SR.GetString("TraceSourceBase"), System.Transactions.SR.GetString("TransactionScopeInvalidNesting"), null); } if (DiagnosticTrace.Warning) { if (null == currentScope.expectedCurrent) { TransactionScopeNestedIncorrectlyTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), TransactionTraceIdentifier.Empty); } else { TransactionScopeNestedIncorrectlyTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), currentScope.expectedCurrent.TransactionTraceId); } } currentScope.complete = false; try { currentScope.InternalDispose(); } catch (TransactionException) { } currentScope = this.threadContextData.CurrentScope; this.complete = false; } } else if ((this.interopOption == EnterpriseServicesInteropOption.None) && (((null != this.expectedCurrent) && !this.expectedCurrent.Equals(transaction)) || ((null != transaction) && (null == this.expectedCurrent)))) { if (DiagnosticTrace.Warning) { TransactionTraceIdentifier identifier; TransactionTraceIdentifier identifier2; if (null == transaction) { identifier2 = TransactionTraceIdentifier.Empty; } else { identifier2 = transaction.TransactionTraceId; } if (null == this.expectedCurrent) { identifier = TransactionTraceIdentifier.Empty; } else { identifier = this.expectedCurrent.TransactionTraceId; } TransactionScopeCurrentChangedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), identifier, identifier2); } if (exception == null) { exception = TransactionException.CreateInvalidOperationException(System.Transactions.SR.GetString("TraceSourceBase"), System.Transactions.SR.GetString("TransactionScopeIncorrectCurrent"), null); } if (null != transaction) { try { transaction.Rollback(); } catch (TransactionException) { } catch (ObjectDisposedException) { } } this.complete = false; } flag = true; } finally { if (!flag) { this.PopScope(); } } this.InternalDispose(); if (exception != null) { throw exception; } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), "TransactionScope.Dispose"); } } }
public void ExplicitTransactionWithDependentTransaction() { using (var t = new CommittableTransaction()) using (new TxScope(t, NullLogger.Instance)) { Console.WriteLine("T1 STATUS: {0}", t.TransactionInformation.Status); using (var c = GetConnection()) using (var cmd = c.CreateCommand()) { cmd.CommandText = "SELECT TOP 1 Val FROM Thing"; var scalar = (double)cmd.ExecuteScalar(); Console.WriteLine("T1 STATUS: {0}", t.TransactionInformation.Status); Console.WriteLine("got val {0}, disposing command and connection", scalar); } using (var t2 = t.DependentClone(DependentCloneOption.RollbackIfNotComplete)) using (new TxScope(t2, NullLogger.Instance)) using (var c = GetConnection()) using (var cmd = c.CreateCommand()) { t2.TransactionCompleted += (s, ea) => Console.WriteLine("::: T2 TransactionCompleted: {0}", ea.Transaction.TransactionInformation.LocalIdentifier); cmd.CommandText = "DELETE FROM Thing"; Console.WriteLine("T2: EXECUTING NON QUERY"); cmd.ExecuteNonQuery(); Console.WriteLine("T2: Enlisting volatile"); t2.EnlistVolatile(new VolatileResource(false), EnlistmentOptions.None); Console.WriteLine("T2: COMPLETE-CALL"); t2.Complete(); Console.WriteLine("T2 STATUS: {0}", t2.TransactionInformation.Status); } Console.WriteLine("T1: COMMITTING, status: {0}", t.TransactionInformation.Status); try { t.Commit(); } catch (TransactionAbortedException e) { Console.WriteLine("TransactionAbortedException, {0}", e); t.Rollback(e); } Console.WriteLine("T1 STATUS: {0}", t.TransactionInformation.Status); Console.WriteLine("T1: DISPOSING"); } }
/// <summary> /// /// </summary> /// <returns>Retrieved work item or null if not found, didn't pass pre-check, etc.</returns> private WorkItem GetWorkItemFromQueue () { //TODO: Pay great attention here, now workItemCandidate is an instance field!!! (SD) workItemCandidate = null; #region Get message from queue var transaction = new CommittableTransaction(); try { Job job; using (DependentTransaction dependentTransaction = transaction.DependentClone(DependentCloneOption.BlockCommitUntilComplete)) { using (var scope = new TransactionScope(dependentTransaction)) { job = ItemProvider.GetNextItem(); scope.Complete(); } dependentTransaction.Complete(); } if (job != null) { PerformanceHandler.HandleEvent("Reads From Queue/sec", 1); workItemCandidate = new RequestWorkItem(job.ContextIdentifier.InternalId, 0, WorkItemState.AvailableForProcessing, SubmissionPriority.Normal, null, false, false, "test", new ContextIdentifier()); // Set transaction on the work item workItemCandidate.Transaction = transaction; workItemCandidate.RetrievedAt = DateTime.Now; workItemCandidate.MessageBody = SerializationUtility.Serialize2ByteArray(job); } else { workItemCandidate = null; } FailureExceptionHandler.ResetState(); } catch (Exception ex) { try { // Rollback the commitable transaction transaction.Rollback(ex); } finally { transaction.Dispose(); } Log.Source.TraceData(TraceEventType.Error, ProducerMessage.ErrorDuringObtainingTheWorkItem, new ContextualLogEntry { Message = "Exception happened when trying to get item from the message queue (" + "queue.QueuePath" + "). " + Environment.NewLine + ex , ContextIdentifier = ((workItemCandidate != null) ? workItemCandidate.ContextIdentifier : new ContextIdentifier()) }); // To review what is the required handling here for us (SD) if (ExecutionState == ProcessExecutionState.Running) { FailureExceptionType type = FailureExceptionHandler.HandleFailure(ex); if (type == FailureExceptionType.NonRecoverable) Stop(); } else { if (workItemCandidate != null) { Log.Source.TraceData(TraceEventType.Information, ProducerMessage.RetrievedMessageReturnedToTheRetrievalQueue, new ContextualLogEntry { Message = string.Format ( "'{0}': Retrieved Recurrence(Id = {1}) Successfully Saved to the {2} queue", Name, workItemCandidate.Id, "" ), ContextIdentifier = workItemCandidate.ContextIdentifier }); return null; } } if (workItemCandidate == null) return null; } #endregion Get message from queue #region Pre-processing checks WorkItem workItem = AssignWorkItemFromCandidate(workItemCandidate); #endregion Pre-processing checks // Return retrieved work item (or null) return workItem; }
internal static void SafeRollbackTransaction(CommittableTransaction transaction) { if (transaction != null) { try { transaction.Rollback(); transaction.Dispose(); } catch (TransactionException transactionException) { if (TD.RoutingServiceHandledExceptionIsEnabled()) { TD.RoutingServiceHandledException(null, transactionException); } } catch (ObjectDisposedException disposedException) { if (TD.RoutingServiceHandledExceptionIsEnabled()) { TD.RoutingServiceHandledException(null, disposedException); } } } }
private void button84_Click(object sender, EventArgs e) { CommittableTransaction tx = null; try { using (tx = new CommittableTransaction()) { using (SqlConnection conn1 = new SqlConnection(Properties.Settings.Default.NorthwindConnectionString)) { using (SqlCommand myCommand = new SqlCommand()) { myCommand.Connection = conn1; conn1.Open(); conn1.EnlistTransaction(tx); //Restore database to near it's original condition so sample will work correctly. myCommand.CommandText = "DELETE FROM Region WHERE (RegionID = 100) OR (RegionID = 101)"; myCommand.ExecuteNonQuery(); //Insert the first record. myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'MidWestern')"; myCommand.ExecuteNonQuery(); //測試交易失敗用 //Insert the first record. myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'MidWestern')"; myCommand.ExecuteNonQuery(); //Insert the second record. myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'MidEastern')"; myCommand.ExecuteNonQuery(); tx.Commit(); MessageBox.Show("trans. Successfully"); } } } } catch (TransactionException ex) { MessageBox.Show(ex.Message); tx.Rollback(); } catch (Exception ex) { MessageBox.Show("trans. roll back " + ex.Message); } }
public void ExplicitTransaction7 () { CommittableTransaction ct = new CommittableTransaction (); IntResourceManager irm = new IntResourceManager (1); irm.Value = 2; ct.Commit (); /* Cannot accept any new work now, so TransactionException */ ct.Rollback (); }
public void ExplicitTransactionRollback () { Assert.IsNull (Transaction.Current, "Ambient transaction exists (before)"); CommittableTransaction ct = new CommittableTransaction (); Transaction oldTransaction = Transaction.Current; Transaction.Current = ct; IntResourceManager irm = new IntResourceManager (1); irm.Value = 2; Assert.AreEqual (TransactionStatus.Active, ct.TransactionInformation.Status, "#35"); ct.Rollback (); Assert.AreEqual (1, irm.Value, "#36"); Assert.AreEqual (TransactionStatus.Aborted, ct.TransactionInformation.Status, "#37"); Transaction.Current = oldTransaction; }
/// <summary> /// /// </summary> /// <param name="priority"></param> /// <returns>Retrieved work item or null if not found, didn't pass pre-check, etc.</returns> private WorkItem GetWorkItemFromQueue(SubmissionPriority priority) { //TODO: Pay great attention here, now workItemCandidate is an instance field!!! (SD) workItemCandidate = null; WorkItem workItem = null; Tools.Commands.Implementation.IF1.req item = null; Trace.CorrelationManager.ActivityId = Guid.NewGuid(); #region Get message from queue var transaction = new CommittableTransaction(); try { #region Get next job from the queue //var using (DependentTransaction dependentTransaction = transaction.DependentClone(DependentCloneOption.BlockCommitUntilComplete)) { using (var scope = new TransactionScope(dependentTransaction)) { //TODO: (SD) Provide timeout option item = new Tools.Commands.Implementation.IF1.req { reqId = (++IdSequence).ToString(), processingStatus = "P", errorDesc = "ok", returnValue = "ok", updateMechanism = "JMS" }; scope.Complete(); } dependentTransaction.Complete(); if (item == null) { // if token is equal to null then commit here, as // consumer will not get to the item anyway. if (transaction.TransactionInformation.Status == TransactionStatus.Active) transaction.Commit(); } } #endregion #region If job is not null create a work item for it if (item != null) { workItemCandidate = new RequestWorkItem(0, 0, WorkItemState.AvailableForProcessing, SubmissionPriority.Normal, Encoding.UTF8.GetBytes(SerializationUtility.Serialize2String(item)), false, false, this.Name, new ContextIdentifier { InternalId = 0, ExternalReference = IdSequence.ToString(), ExternalId = IdSequence.ToString() }) { Transaction = transaction, RetrievedAt = DateTime.Now }; //**Trace.CorrelationManager.ActivityId = .ContextUid; Log.Source.TraceEvent(TraceEventType.Start, 0, "Received the item " + item); // Set transaction on the work item } #endregion this.FailureExceptionHandler.ResetState(); } catch (Exception ex) { try { // Rollback the commitable transaction transaction.Rollback(ex); } finally { transaction.Dispose(); } Log.TraceData(Log.Source, TraceEventType.Error, ProducerMessage.ErrorDuringObtainingTheWorkItem, new ContextualLogEntry { Message = "Exception happened when trying to get item " + Environment.NewLine + ex, ContextIdentifier = ((workItemCandidate != null) ? workItemCandidate.ContextIdentifier : new ContextIdentifier()) }); // To review what is the required handling here for us (SD) if (ExecutionState == ProcessExecutionState.Running) { FailureExceptionType type = this.FailureExceptionHandler.HandleFailure(ex); if (type == FailureExceptionType.NonRecoverable) this.Stop(); } else { if (workItemCandidate != null) { Log.TraceData(Log.Source, System.Diagnostics.TraceEventType.Information, ProducerMessage.RetrievedMessageReturnedToTheRetrievalQueue, new ContextualLogEntry { Message = string.Format( "'{0}': Retrieved Recurrence(Id = {1}) Successfully Saved to the {2} queue", Name, workItemCandidate.Id, "" ), ContextIdentifier = workItemCandidate.ContextIdentifier }); return null; } } } #endregion Get message from queue #region Pre-processing checks // Convert queue message to work item // In case sql broker no need to do (SD) if (workItemCandidate != null) { #region WorkItem Diagnostics workItemCandidate.AttachNote("Received from the " + priority + " Queue "); #endregion WorkItem Diagnostics // TODO: //**SD1 - Provide the check for // No checks done now, see the DB driven implementation for the checks samples (SD) // It means as well that we can simply assign item candidate to be our work item workItem = workItemCandidate; // TODO: (SD) Message body will be the xml retrieved from the sql broker //**message.GetObjectProperty } #endregion Pre-processing checks // Return retrieved work item (or null) return workItem; }
public void ExternalTransactionRollback() { TestDatabase database = new TestDatabase(); CommittableTransaction external = new CommittableTransaction(); NMemory.Transactions.Transaction transaction = NMemory.Transactions.Transaction.Create(external); database.Members.Insert(new Member { Id = "A" }, transaction); external.Rollback(); Assert.AreEqual(database.Members.Count, 0); Assert.IsFalse(database.Members.Any(m => m.Id == "A")); }
public static void ListenerThreadProc(object queueListenerConfig) { QueueListenerConfig config = (QueueListenerConfig) queueListenerConfig; while (!stopping) { TransactionOptions to = new TransactionOptions(); to.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; to.Timeout = TimeSpan.MaxValue; CommittableTransaction tran = new CommittableTransaction(to); try { using (var con = new SqlConnection(config.ConnectionString)) { con.Open(); con.EnlistTransaction(tran); byte[] message = ServiceBrokerUtils.GetMessage(config.QueueName, con, TimeSpan.FromSeconds(10)); if (message == null) //no message available { tran.Commit(); con.Close(); continue; } try { if (config.EnlistMessageProcessor) { using (var ts = new TransactionScope(tran)) { config.MessageProcessor(message); ts.Complete(); } } else { config.MessageProcessor(message); } } catch (SqlException ex) //catch selected exceptions thrown by the MessageProcessor { config.FailedMessageProcessor(message, con, ex); } tran.Commit(); // the message processing succeeded or the FailedMessageProcessor ran so commit the RECEIVE con.Close(); } } catch (SqlException ex) { System.Diagnostics.Trace.Write("Error processing message from " + config.QueueName + ": " + ex.Message); tran.Rollback(); tran.Dispose(); Thread.Sleep(1000); } ///catch any other non-fatal exceptions that should not stop the listener loop. catch (Exception ex) { Trace.WriteLine("Unexpected Exception in Thread Proc for " + config.QueueName + ". Thread Proc is exiting: " + ex.Message); tran.Rollback(); tran.Dispose(); return; } } }