internal void ResolveOutcome(ref MessageRpc rpc) { if ((rpc.InstanceContext != null) && (rpc.transaction != null)) { TransactionInstanceContextFacet transaction = rpc.InstanceContext.Transaction; if (transaction != null) { transaction.CheckIfTxCompletedAndUpdateAttached(ref rpc, this.isConcurrent); } rpc.Transaction.Complete(rpc.Error); } }
internal void ResolveTransaction(ref MessageRpc rpc) { InstanceContext context; if (rpc.Operation.HasDefaultUnhandledActionInvoker) { return; } Transaction transactionForInstance = null; if (rpc.Operation.IsInsideTransactedReceiveScope) { IInstanceTransaction invoker = rpc.Operation.Invoker as IInstanceTransaction; if (invoker != null) { transactionForInstance = invoker.GetTransactionForInstance(rpc.OperationContext); } if ((transactionForInstance != null) && DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0xe000f, System.ServiceModel.SR.GetString("TraceCodeTxSourceTxScopeRequiredUsingExistingTransaction", new object[] { transactionForInstance.TransactionInformation.LocalIdentifier, rpc.Operation.Name })); } } else { transactionForInstance = this.GetInstanceContextTransaction(ref rpc); } Transaction transaction3 = null; try { transaction3 = TransactionMessageProperty.TryGetTransaction(rpc.Request); } catch (TransactionException exception) { DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateFault(System.ServiceModel.SR.GetString("SFxTransactionUnmarshalFailed", new object[] { exception.Message }), "TransactionUnmarshalingFailed", false)); } if (rpc.Operation.TransactionRequired) { if (transaction3 == null) { goto Label_0256; } if (this.isTransactedReceiveChannelDispatcher) { if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0xe0001, System.ServiceModel.SR.GetString("TraceCodeTxSourceTxScopeRequiredIsTransactedTransport", new object[] { transaction3.TransactionInformation.LocalIdentifier, rpc.Operation.Name })); } goto Label_0256; } if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0xe0002, System.ServiceModel.SR.GetString("TraceCodeTxSourceTxScopeRequiredIsTransactionFlow", new object[] { transaction3.TransactionInformation.LocalIdentifier, rpc.Operation.Name })); } if (PerformanceCounters.PerformanceCountersEnabled) { PerformanceCounters.TxFlowed(PerformanceCounters.GetEndpointDispatcher(), rpc.Operation.Name); } bool flag = false; if (rpc.Operation.IsInsideTransactedReceiveScope) { flag = transaction3.Equals(transactionForInstance); } else { flag = transaction3 == transactionForInstance; } if (flag) { goto Label_0256; } try { transaction3 = transaction3.DependentClone(DependentCloneOption.RollbackIfNotComplete); goto Label_0256; } catch (TransactionException exception2) { DiagnosticUtility.ExceptionUtility.TraceHandledException(exception2, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true)); } } if ((transaction3 != null) && this.isTransactedReceiveChannelDispatcher) { try { if (rpc.TransactedBatchContext != null) { rpc.TransactedBatchContext.ForceCommit(); rpc.TransactedBatchContext = null; } else { TransactionInstanceContextFacet.Complete(transaction3, null); } } finally { transaction3.Dispose(); transaction3 = null; } } Label_0256: context = rpc.InstanceContext; if (context.Transaction.ShouldReleaseInstance && !this.isConcurrent) { if (context.Behavior.ReleaseServiceInstanceOnTransactionComplete) { context.ReleaseServiceInstance(); if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0xe000c, System.ServiceModel.SR.GetString("TraceCodeTxReleaseServiceInstanceOnCompletion", new object[] { transactionForInstance.TransactionInformation.LocalIdentifier })); } } context.Transaction.ShouldReleaseInstance = false; if ((transaction3 == null) || (transaction3 == transactionForInstance)) { rpc.Transaction.Current = transactionForInstance; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true)); } transactionForInstance = null; } if (rpc.Operation.TransactionRequired) { if (transaction3 == null) { if (transactionForInstance != null) { transaction3 = transactionForInstance; if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0xe0003, System.ServiceModel.SR.GetString("TraceCodeTxSourceTxScopeRequiredIsAttachedTransaction", new object[] { transaction3.TransactionInformation.LocalIdentifier, rpc.Operation.Name })); } } else { transaction3 = CreateTransaction(this.isolation, this.timeout); if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0xe0004, System.ServiceModel.SR.GetString("TraceCodeTxSourceTxScopeRequiredIsCreateNewTransaction", new object[] { transaction3.TransactionInformation.LocalIdentifier, rpc.Operation.Name })); } } } if ((this.isolation != IsolationLevel.Unspecified) && (transaction3.IsolationLevel != this.isolation)) { throw TraceUtility.ThrowHelperError(CreateFault(System.ServiceModel.SR.GetString("IsolationLevelMismatch2", new object[] { transaction3.IsolationLevel, this.isolation }), "TransactionIsolationLevelMismatch", false), rpc.Request); } rpc.Transaction.Current = transaction3; rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Current, true); try { rpc.Transaction.Clone = transaction3.Clone(); if (rpc.Operation.IsInsideTransactedReceiveScope) { rpc.Transaction.CreateDependentClone(); } } catch (ObjectDisposedException exception3) { DiagnosticUtility.ExceptionUtility.TraceHandledException(exception3, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true)); } rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Clone, false); rpc.OperationContext.TransactionFacet = rpc.Transaction; if (!rpc.Operation.TransactionAutoComplete) { rpc.Transaction.SetIncomplete(); } } }
internal void ResolveTransaction(ref MessageRpc rpc) { if (rpc.Operation.HasDefaultUnhandledActionInvoker) { // we ignore unhandled operations return; } Transaction contextTransaction = null; //If we are inside a TransactedReceiveScope in workflow, then we need to look into the PPD and not the InstanceContext //to get the contextTransaction if (rpc.Operation.IsInsideTransactedReceiveScope) { // We may want to use an existing transaction for the instance. IInstanceTransaction instanceTransaction = rpc.Operation.Invoker as IInstanceTransaction; if (instanceTransaction != null) { contextTransaction = instanceTransaction.GetTransactionForInstance(rpc.OperationContext); } if (contextTransaction != null) { if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredUsingExistingTransaction, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredUsingExistingTransaction, contextTransaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } } } else { contextTransaction = this.GetInstanceContextTransaction(ref rpc); } Transaction transaction = null; try { transaction = TransactionMessageProperty.TryGetTransaction(rpc.Request); } catch (TransactionException e) { DiagnosticUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionUnmarshalFailed, e.Message), FaultCodeConstants.Codes.TransactionUnmarshalingFailed, false)); } if (rpc.Operation.TransactionRequired) { if (transaction != null) { if (this.isTransactedReceiveChannelDispatcher) { if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredIsTransactedTransport, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsTransactedTransport, transaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } } else { if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredIsTransactionFlow, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsTransactionFlow, transaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } if (PerformanceCounters.PerformanceCountersEnabled) { PerformanceCounters.TxFlowed(PerformanceCounters.GetEndpointDispatcher(), rpc.Operation.Name); } bool sameTransaction = false; if (rpc.Operation.IsInsideTransactedReceiveScope) { sameTransaction = transaction.Equals(contextTransaction); } else { sameTransaction = transaction == contextTransaction; } if (!sameTransaction) { try { transaction = transaction.DependentClone(DependentCloneOption.RollbackIfNotComplete); } catch (TransactionException e) { DiagnosticUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } } } } } else { // We got a transaction from the ChannelHandler. // Transport is transacted. // But operation doesn't require the transaction, so no one ever will commit it. // Because of that we have to commit it here. if (transaction != null && this.isTransactedReceiveChannelDispatcher) { try { if (null != rpc.TransactedBatchContext) { rpc.TransactedBatchContext.ForceCommit(); rpc.TransactedBatchContext = null; } else { TransactionInstanceContextFacet.Complete(transaction, null); } } finally { transaction.Dispose(); transaction = null; } } } InstanceContext context = rpc.InstanceContext; if (context.Transaction.ShouldReleaseInstance && !this.isConcurrent) { if (context.Behavior.ReleaseServiceInstanceOnTransactionComplete) { context.ReleaseServiceInstance(); if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.TxReleaseServiceInstanceOnCompletion, SR.GetString(SR.TraceCodeTxReleaseServiceInstanceOnCompletion, contextTransaction.TransactionInformation.LocalIdentifier) ); } } context.Transaction.ShouldReleaseInstance = false; if (transaction == null || transaction == contextTransaction) { rpc.Transaction.Current = contextTransaction; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } else { contextTransaction = null; } } if (rpc.Operation.TransactionRequired) { if (transaction == null) { if (contextTransaction != null) { transaction = contextTransaction; if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredIsAttachedTransaction, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsAttachedTransaction, transaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } } else { transaction = TransactionBehavior.CreateTransaction(this.isolation, this.timeout); if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredIsCreateNewTransaction, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsCreateNewTransaction, transaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } } } if ((this.isolation != IsolationLevel.Unspecified) && (transaction.IsolationLevel != this.isolation)) { throw TraceUtility.ThrowHelperError(TransactionBehavior.CreateFault (SR.GetString(SR.IsolationLevelMismatch2, transaction.IsolationLevel, this.isolation), FaultCodeConstants.Codes.TransactionIsolationLevelMismatch, false), rpc.Request); } rpc.Transaction.Current = transaction; rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Current, true); try { rpc.Transaction.Clone = transaction.Clone(); if (rpc.Operation.IsInsideTransactedReceiveScope) { //It is because we want to synchronize the dispatcher processing of messages with the commit //processing that is started by the completion of a TransactedReceiveScope. We need to make sure //that all the dispatcher processing is done and we can do that by creating a blocking dependent clone and only //completing it after all of the message processing is done for a given TransactionRpcFacet rpc.Transaction.CreateDependentClone(); } } catch (ObjectDisposedException e)//transaction may be async aborted { DiagnosticUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Clone, false); rpc.OperationContext.TransactionFacet = rpc.Transaction; if (!rpc.Operation.TransactionAutoComplete) { rpc.Transaction.SetIncomplete(); } } }