TransactedReceiveScope.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Activities / System / ServiceModel / Activities / TransactedReceiveScope.cs / 1305376 / TransactedReceiveScope.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.ServiceModel.Activities 
{
    using System; 
    using System.Activities; 
    using System.Activities.Expressions;
    using System.Activities.Statements; 
    using System.Activities.Validation;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel; 
    using System.Runtime;
    using System.Runtime.Collections; 
    using System.Windows.Markup; 
    using SR2 = System.ServiceModel.Activities.SR;
 
    [ContentProperty("Body")]
    public sealed class TransactedReceiveScope : NativeActivity
    {
        Variable transactionHandle; 
        Collection variables;
        const string AbortInstanceOnTransactionFailurePropertyName = "AbortInstanceOnTransactionFailure"; 
        const string RequestPropertyName = "Request"; 
        const string BodyPropertyName = "Body";
        Variable isNested; 
        static AsyncCallback transactionCommitCallback;

        public TransactedReceiveScope()
        { 
            this.transactionHandle = new Variable
            { 
                Name = "TransactionHandle" 
            };
            this.isNested = new Variable(); 

            base.Constraints.Add(ProcessChildSubtreeConstraints());
        }
 
        [DefaultValue(null)]
        public Receive Request 
        { 
            get;
            set; 
        }

        [DefaultValue(null)]
        public Activity Body 
        {
            get; 
            set; 
        }
 
        public Collection Variables
        {
            get
            { 
                if (this.variables == null)
                { 
                    this.variables = new ValidatingCollection 
                    {
                        // disallow null values 
                        OnAddValidationCallback = item =>
                        {
                            if (item == null)
                            { 
                                throw FxTrace.Exception.ArgumentNull("item");
                            } 
                        } 
                    };
                } 
                return this.variables;
            }
        }
 
        internal static AsyncCallback TransactionCommitAsyncCallback
        { 
            get 
            {
                if (transactionCommitCallback == null) 
                {
                    transactionCommitCallback = Fx.ThunkCallback(new AsyncCallback(TransactionCommitCallback));
                }
 
                return transactionCommitCallback;
            } 
        } 

        Constraint ProcessChildSubtreeConstraints() 
        {
            DelegateInArgument element = new DelegateInArgument { Name = "element" };
            DelegateInArgument validationContext = new DelegateInArgument { Name = "validationContext" };
            DelegateInArgument child = new DelegateInArgument { Name = "child" }; 
            Variable nestedCompensableActivity = new Variable
            { 
                Name = "nestedCompensableActivity" 
            };
 
            return new Constraint
            {
                Body = new ActivityAction
                { 
                    Argument1 = element,
                    Argument2 = validationContext, 
                    Handler = new Sequence 
                    {
                        Variables = { nestedCompensableActivity }, 
                        Activities =
                        {
                            new ForEach
                            { 
                                Values = new GetChildSubtree
                                { 
                                    ValidationContext = validationContext, 
                                },
                                Body = new ActivityAction 
                                {
                                    Argument = child,
                                    Handler = new Sequence
                                    { 
                                        Activities =
                                        { 
                                            new If() 
                                            {
                                                Condition = new Equal 
                                                {
                                                    Left = new ObtainType
                                                    {
                                                        Input = new InArgument(child) 
                                                    },
                                                    Right = new InArgument(context => typeof(TransactionScope)) 
                                                }, 
                                                Then = new AssertValidation
                                                { 
                                                    IsWarning = true,
                                                    Assertion = new NestedChildTransactionScopeActivityAbortInstanceFlagValidator
                                                    {
                                                         Child = child 
                                                    },
                                                    Message = new InArgument(env => SR.AbortInstanceOnTransactionFailureDoesNotMatch(child.Get(env).DisplayName, this.DisplayName)), 
                                                    PropertyName = AbortInstanceOnTransactionFailurePropertyName 
                                                }
                                            }, 
                                            new If()
                                            {
                                                Condition = new Equal
                                                { 
                                                    Left = new ObtainType
                                                    { 
                                                        Input = new InArgument(child) 
                                                    },
                                                    Right = new InArgument(context => typeof(CompensableActivity)) 
                                                },
                                                Then = new Assign
                                                {
                                                    To = new OutArgument(nestedCompensableActivity), 
                                                    Value = new InArgument(true)
                                                } 
                                            } 
                                        }
                                    } 
                                }
                            },
                            new AssertValidation
                            { 
                                Assertion = new InArgument(env => !nestedCompensableActivity.Get(env)),
                                Message = new InArgument(SR2.CompensableActivityInsideTransactedReceiveScope), 
                                PropertyName = BodyPropertyName 
                            }
                        } 
                    }
                }
            };
        } 

        protected override void CacheMetadata(NativeActivityMetadata metadata) 
        { 
            if (this.Request == null)
            { 
                metadata.AddValidationError(new ValidationError(SR2.TransactedReceiveScopeMustHaveValidReceive(this.DisplayName), false, RequestPropertyName));
            }
            metadata.AddChild(this.Request);
            metadata.AddChild(this.Body); 
            metadata.SetVariablesCollection(this.Variables);
            metadata.AddImplementationVariable(this.transactionHandle); 
            metadata.AddImplementationVariable(this.isNested); 
        }
 
        protected override void Execute(NativeActivityContext context)
        {
            if (this.Request == null)
            { 
                throw FxTrace.Exception.AsError(new ValidationException(SR2.TransactedReceiveScopeRequiresReceive(this.DisplayName)));
            } 
            // we have to do this in code since we aren't fully modeled (in order for 
            // dynamic update to work correctly)
            RuntimeTransactionHandle handleInstance = this.transactionHandle.Get(context); 
            Fx.Assert(handleInstance != null, "RuntimeTransactionHandle is null");

            //This is used by InternalReceiveMessage to update the InitiatingTransaction so that we can later call Commit/Complete on it
            context.Properties.Add(TransactedReceiveData.TransactedReceiveDataExecutionPropertyName, new TransactedReceiveData()); 

            RuntimeTransactionHandle foundHandle = context.Properties.Find(handleInstance.ExecutionPropertyName) as RuntimeTransactionHandle; 
            if (foundHandle == null) 
            {
                context.Properties.Add(handleInstance.ExecutionPropertyName, handleInstance); 
            }
            else
            {
                 //nested case 
                if (foundHandle.SuppressTransaction)
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.CannotNestTransactedReceiveScopeWhenAmbientHandleIsSuppressed(this.DisplayName))); 
                }
 
                // Verify if TRS is root and if the foundHandle is not from the parent HandleScope
                if (foundHandle.GetCurrentTransaction(context) != null)
                {
                    handleInstance = foundHandle; 
                    this.isNested.Set(context, true);
                } 
            } 
            context.ScheduleActivity(this.Request, new CompletionCallback(OnReceiveCompleted));
        } 

        void OnReceiveCompleted(NativeActivityContext context, ActivityInstance completedInstance)
        {
            if (this.Body != null) 
            {
                context.ScheduleActivity(this.Body, new CompletionCallback(OnBodyCompleted)); 
            } 
            else if (completedInstance.State == ActivityInstanceState.Closed)
            { 
                OnBodyCompleted(context, completedInstance);
            }
        }
 
        void OnBodyCompleted(NativeActivityContext context, ActivityInstance completedInstance)
        { 
            TransactedReceiveData transactedReceiveData = context.Properties.Find(TransactedReceiveData.TransactedReceiveDataExecutionPropertyName) as TransactedReceiveData; 
            Fx.Assert(transactedReceiveData != null, "TransactedReceiveScope.OnBodyComplete - transactedreceivedata is null");
 
            //Non Nested
            if (!this.isNested.Get(context))
            {
                Fx.Assert(transactedReceiveData.InitiatingTransaction != null, "TransactedReceiveScope.OnBodyComplete - Initiating transaction is null"); 
                System.Transactions.CommittableTransaction committableTransaction = transactedReceiveData.InitiatingTransaction as System.Transactions.CommittableTransaction;
                //If the initiating transaction was a committable transaction => this is a server side only transaction. Commit it here instead of letting the dispatcher deal with it 
                //since we are Auto Complete = false and we want the completion of the TransactedReceiveScope to initiate the Commit. 
                if (committableTransaction != null)
                { 
                    committableTransaction.BeginCommit(TransactionCommitAsyncCallback, committableTransaction);
                }
                else
                { 
                    //If the initiating transaction was a dependent transaction instead => this is a flowed in transaction, let's just complete the dependent clone
                    System.Transactions.DependentTransaction dependentTransaction = transactedReceiveData.InitiatingTransaction as System.Transactions.DependentTransaction; 
                    Fx.Assert(dependentTransaction != null, "TransactedReceiveScope.OnBodyComplete - DependentClone was null"); 
                    dependentTransaction.Complete();
                } 
            }
            else //Nested scenario - e.g TRS inside a TSA and in a flow case :- we still need to complete the dependent transaction
            {
                System.Transactions.DependentTransaction dependentTransaction = transactedReceiveData.InitiatingTransaction as System.Transactions.DependentTransaction; 
                if (dependentTransaction != null)
                { 
                    dependentTransaction.Complete(); 
                }
            } 
        }

        static void TransactionCommitCallback(IAsyncResult result)
        { 
            System.Transactions.CommittableTransaction committableTransaction = result.AsyncState as System.Transactions.CommittableTransaction;
            Fx.Assert(committableTransaction != null, "TransactedReceiveScope - In the static TransactionCommitCallback, the committable transaction was null"); 
            try 
            {
                committableTransaction.EndCommit(result); 
            }
            catch (System.Transactions.TransactionException ex)
            {
                //At this point, the activity has completed. Since the runtime is enlisted in the transaction, it knows that the transaction aborted. 
                //The runtime will do the right thing based on the AbortInstanceOnTransactionFailure flag. We simply trace out that the call to EndCommit failed from this static callback
                if (TD.TransactedReceiveScopeEndCommitFailedIsEnabled()) 
                { 
                    TD.TransactedReceiveScopeEndCommitFailed(committableTransaction.TransactionInformation.LocalIdentifier, ex.Message);
                } 
            }
        }

        // 
        class ObtainType : CodeActivity
        { 
            public ObtainType() 
            {
            } 

            public InArgument Input
            {
                get; 
                set;
            } 
 
            protected override Type Execute(CodeActivityContext context)
            { 
                return this.Input.Get(context).GetType();
            }
        }
 
        class NestedChildTransactionScopeActivityAbortInstanceFlagValidator : CodeActivity
        { 
            public InArgument Child 
            {
                get; 
                set;
            }

            protected override bool Execute(CodeActivityContext context) 
            {
                Activity child = this.Child.Get(context); 
 
                if (child != null)
                { 
                    TransactionScope transactionScopeActivity = child as TransactionScope;
                    Fx.Assert(transactionScopeActivity != null, "Child was not of expected type");

                    //We dont care whether the flag was explicitly set 
                    // a) We cant tell whether the flag was explicitly set on the child
                    // b) This is mostly a scenario where the WF calls into a library. It is OK 
                    // to flag the warning either 

                    return transactionScopeActivity.AbortInstanceOnTransactionFailure; 
                }

                return true;
            } 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK