예제 #1
0
        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();
                }
            }
        }