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
- SqlNotificationRequest.cs
- WindowsTokenRoleProvider.cs
- XPathCompileException.cs
- SqlBulkCopyColumnMappingCollection.cs
- SplitterPanel.cs
- NullableBoolConverter.cs
- TypographyProperties.cs
- QilXmlWriter.cs
- BookmarkScope.cs
- DataGridHeaderBorder.cs
- ReliableChannelBinder.cs
- ZoneMembershipCondition.cs
- GeneralTransform3DTo2D.cs
- Constants.cs
- ResourceReferenceKeyNotFoundException.cs
- TypeElementCollection.cs
- LightweightCodeGenerator.cs
- PagePropertiesChangingEventArgs.cs
- CapabilitiesPattern.cs
- ProcessHostServerConfig.cs
- PropertyPathWorker.cs
- Trace.cs
- FileChangesMonitor.cs
- ResourceExpression.cs
- ImageButton.cs
- GenericUI.cs
- BooleanProjectedSlot.cs
- QilDataSource.cs
- DesigntimeLicenseContext.cs
- GridPattern.cs
- BuildProviderAppliesToAttribute.cs
- TokenBasedSet.cs
- ConfigXmlElement.cs
- ExpressionEditorAttribute.cs
- ThreadNeutralSemaphore.cs
- EventMappingSettings.cs
- TableRowGroup.cs
- HttpCapabilitiesSectionHandler.cs
- DateTimeConverter2.cs
- ButtonBaseAutomationPeer.cs
- SqlProcedureAttribute.cs
- DrawTreeNodeEventArgs.cs
- Int16Storage.cs
- UpDownEvent.cs
- TryLoadRunnableWorkflowCommand.cs
- TextClipboardData.cs
- MenuItem.cs
- ModelEditingScope.cs
- ReturnType.cs
- PublisherMembershipCondition.cs
- RangeValidator.cs
- TraceEventCache.cs
- ParameterReplacerVisitor.cs
- TitleStyle.cs
- GifBitmapEncoder.cs
- metadatamappinghashervisitor.hashsourcebuilder.cs
- WmlValidatorAdapter.cs
- StorageModelBuildProvider.cs
- TransformDescriptor.cs
- RepeaterCommandEventArgs.cs
- HttpServerVarsCollection.cs
- DurableOperationContext.cs
- SqlWebEventProvider.cs
- LayoutEditorPart.cs
- Int16.cs
- CodeTypeOfExpression.cs
- SignedXml.cs
- XmlByteStreamReader.cs
- Function.cs
- GraphicsPathIterator.cs
- TextFindEngine.cs
- Properties.cs
- TableCellCollection.cs
- PropertyDescriptorComparer.cs
- SafeNativeMethods.cs
- WebPartHeaderCloseVerb.cs
- Slider.cs
- FrameworkContentElement.cs
- CommandConverter.cs
- XmlEncodedRawTextWriter.cs
- BaseTemplateParser.cs
- ComponentEditorPage.cs
- DataSysAttribute.cs
- StoreItemCollection.cs
- ListViewCancelEventArgs.cs
- CompletedAsyncResult.cs
- GroupQuery.cs
- Predicate.cs
- ViewDesigner.cs
- TraceHandler.cs
- ListViewDeleteEventArgs.cs
- StackBuilderSink.cs
- SHA384.cs
- WindowsTreeView.cs
- SessionParameter.cs
- OneToOneMappingSerializer.cs
- ResourceReader.cs
- Math.cs
- XamlSerializer.cs
- XPathNodeInfoAtom.cs