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
- ProcessThreadCollection.cs
- BamlBinaryWriter.cs
- Selection.cs
- InputLanguageProfileNotifySink.cs
- MatrixCamera.cs
- WizardStepBase.cs
- NewExpression.cs
- SoapHeader.cs
- GridViewColumnHeaderAutomationPeer.cs
- StorageEntityContainerMapping.cs
- UTF32Encoding.cs
- EditorZoneBase.cs
- Path.cs
- SchemaCollectionCompiler.cs
- ElementMarkupObject.cs
- ImageListStreamer.cs
- BindingGroup.cs
- HttpProfileBase.cs
- ResourceContainer.cs
- ChtmlTextWriter.cs
- Cursors.cs
- ResourcePart.cs
- AuthorizationSection.cs
- DataMisalignedException.cs
- EventLogPermissionHolder.cs
- FromRequest.cs
- PermissionSetEnumerator.cs
- TableLayoutCellPaintEventArgs.cs
- ShaderEffect.cs
- EditCommandColumn.cs
- TraceSection.cs
- TextTreeTextNode.cs
- SmiEventSink_DeferedProcessing.cs
- XmlSchemaValidator.cs
- MetadataUtil.cs
- DBAsyncResult.cs
- SpeechUI.cs
- WebPartAddingEventArgs.cs
- EventPrivateKey.cs
- GacUtil.cs
- ObjectRef.cs
- Intellisense.cs
- ScriptComponentDescriptor.cs
- TcpProcessProtocolHandler.cs
- DispatcherEventArgs.cs
- MobileControlPersister.cs
- SQLByte.cs
- CreateUserErrorEventArgs.cs
- StylusEditingBehavior.cs
- XmlAtomicValue.cs
- ValidationSummary.cs
- ThemeableAttribute.cs
- ApplicationDirectory.cs
- LineBreakRecord.cs
- StateChangeEvent.cs
- TextLine.cs
- HostingEnvironment.cs
- MetadataImporterQuotas.cs
- HierarchicalDataSourceControl.cs
- PerfCounters.cs
- QueueException.cs
- EntityViewGenerationAttribute.cs
- CipherData.cs
- SafeNativeMethods.cs
- BigIntegerStorage.cs
- PlaceHolder.cs
- EntityStoreSchemaFilterEntry.cs
- WebPartHeaderCloseVerb.cs
- DependencyPropertyDescriptor.cs
- ScalarType.cs
- ParserContext.cs
- RijndaelManagedTransform.cs
- DocumentViewerBase.cs
- DataTableCollection.cs
- Ipv6Element.cs
- StructuralCache.cs
- EncryptedKeyIdentifierClause.cs
- Formatter.cs
- BitFlagsGenerator.cs
- HtmlElementEventArgs.cs
- TypeConverterHelper.cs
- TextEncodedRawTextWriter.cs
- ProcessingInstructionAction.cs
- CompiledAction.cs
- ServiceMemoryGates.cs
- StringStorage.cs
- FontResourceCache.cs
- EntitySetDataBindingList.cs
- SlipBehavior.cs
- StatusStrip.cs
- _DigestClient.cs
- EmptyQuery.cs
- TextSchema.cs
- MultiDataTrigger.cs
- Property.cs
- ConstNode.cs
- DesignerForm.cs
- MasterPage.cs
- NameService.cs
- MediaTimeline.cs