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 { VariabletransactionHandle; 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ElementMarkupObject.cs
- oledbmetadatacolumnnames.cs
- QueryContext.cs
- DBDataPermission.cs
- MethodRental.cs
- SqlConnectionPoolProviderInfo.cs
- InputMethod.cs
- PreProcessor.cs
- HttpCookie.cs
- PipeConnection.cs
- XmlElement.cs
- CompilerErrorCollection.cs
- ThousandthOfEmRealPoints.cs
- TemplateDefinition.cs
- XmlHierarchyData.cs
- XPathNodeList.cs
- SqlProcedureAttribute.cs
- SystemMulticastIPAddressInformation.cs
- TdsValueSetter.cs
- AuthenticationSection.cs
- ConnectionManager.cs
- FilterQueryOptionExpression.cs
- NameNode.cs
- ElementMarkupObject.cs
- NotCondition.cs
- SqlReorderer.cs
- WindowsTreeView.cs
- RadioButton.cs
- SystemParameters.cs
- InvalidDataContractException.cs
- TypeDelegator.cs
- DataGridAddNewRow.cs
- ReaderContextStackData.cs
- SqlAliaser.cs
- StructuredTypeEmitter.cs
- WindowsToolbarAsMenu.cs
- CodeSubDirectoriesCollection.cs
- Symbol.cs
- Base64Decoder.cs
- SqlExpressionNullability.cs
- CodeCatchClauseCollection.cs
- AttributeEmitter.cs
- IISMapPath.cs
- DataGridTextBox.cs
- CannotUnloadAppDomainException.cs
- SystemIPv6InterfaceProperties.cs
- TimeSpanFormat.cs
- CalendarDateRangeChangingEventArgs.cs
- LinkLabelLinkClickedEvent.cs
- SecurityPolicySection.cs
- BooleanConverter.cs
- GcHandle.cs
- TextPointerBase.cs
- DynamicPhysicalDiscoSearcher.cs
- RoleManagerSection.cs
- DocumentScope.cs
- ManagementEventArgs.cs
- Socket.cs
- ElementHost.cs
- Literal.cs
- OutputCacheProfile.cs
- SamlAction.cs
- DrawingAttributes.cs
- _BaseOverlappedAsyncResult.cs
- Constraint.cs
- SortDescription.cs
- RemotingException.cs
- RegistryPermission.cs
- OdbcConnectionOpen.cs
- LinqDataSourceContextEventArgs.cs
- BufferedReadStream.cs
- WebBrowser.cs
- XmlSchemaExporter.cs
- WaveHeader.cs
- SecUtil.cs
- CompositeFontFamily.cs
- TemplateControlBuildProvider.cs
- EditorPartCollection.cs
- PropertyCollection.cs
- DataList.cs
- ColumnMapVisitor.cs
- PeerUnsafeNativeMethods.cs
- WebServiceEnumData.cs
- GrammarBuilderPhrase.cs
- Repeater.cs
- TCEAdapterGenerator.cs
- mediaclock.cs
- CmsInterop.cs
- ItemsPanelTemplate.cs
- WSSecurityXXX2005.cs
- GridViewDeletedEventArgs.cs
- SortAction.cs
- XmlEncodedRawTextWriter.cs
- InsufficientMemoryException.cs
- CleanUpVirtualizedItemEventArgs.cs
- DrawingBrush.cs
- ApplyImportsAction.cs
- securitycriticaldataformultiplegetandset.cs
- prefixendpointaddressmessagefiltertable.cs
- SynchronizingStream.cs