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
- SqlRecordBuffer.cs
- ResourceDescriptionAttribute.cs
- ReadOnlyDataSource.cs
- TemplateBindingExtension.cs
- AuthorizationRuleCollection.cs
- CorePropertiesFilter.cs
- StreamedWorkflowDefinitionContext.cs
- CriticalHandle.cs
- COM2ComponentEditor.cs
- DataRowView.cs
- AxisAngleRotation3D.cs
- UnknownBitmapDecoder.cs
- LinqDataSourceContextEventArgs.cs
- EntityDataSourceStatementEditorForm.cs
- TextSpanModifier.cs
- DateBoldEvent.cs
- IgnoreFileBuildProvider.cs
- DecimalStorage.cs
- Timeline.cs
- FileVersion.cs
- HwndHost.cs
- MimeBasePart.cs
- XmlHelper.cs
- SwitchLevelAttribute.cs
- AssemblyCollection.cs
- StaticFileHandler.cs
- ControlEvent.cs
- HttpListenerException.cs
- DialogResultConverter.cs
- WriteLineDesigner.xaml.cs
- SectionVisual.cs
- MetadataArtifactLoaderXmlReaderWrapper.cs
- ExpressionVisitor.cs
- HttpRequest.cs
- XmlBoundElement.cs
- RuntimeUtils.cs
- ObjectSecurity.cs
- PackageRelationshipCollection.cs
- JournalEntryListConverter.cs
- XmlBinaryWriter.cs
- DetailsViewPagerRow.cs
- Registry.cs
- FloaterParaClient.cs
- SystemFonts.cs
- ReliableDuplexSessionChannel.cs
- PathFigureCollection.cs
- LogArchiveSnapshot.cs
- MissingFieldException.cs
- BuildProvidersCompiler.cs
- RemotingAttributes.cs
- PropertyConverter.cs
- ListSortDescription.cs
- Figure.cs
- CacheAxisQuery.cs
- GorillaCodec.cs
- ConnectionManagementSection.cs
- ReflectTypeDescriptionProvider.cs
- SqlDataSourceView.cs
- ColumnMap.cs
- WpfGeneratedKnownTypes.cs
- Aes.cs
- DataSourceConverter.cs
- Queue.cs
- TriggerCollection.cs
- CompoundFileStreamReference.cs
- Facet.cs
- MetadataArtifactLoaderFile.cs
- ParenthesizePropertyNameAttribute.cs
- DataBoundLiteralControl.cs
- SegmentInfo.cs
- OleTxTransactionInfo.cs
- User.cs
- AssociationSet.cs
- PackageDigitalSignatureManager.cs
- AsyncOperationManager.cs
- WmlTextViewAdapter.cs
- ContextMenu.cs
- AdapterUtil.cs
- PropertyToken.cs
- Closure.cs
- BinaryObjectReader.cs
- ModulesEntry.cs
- DescendantOverDescendantQuery.cs
- XmlAttributeCollection.cs
- Interlocked.cs
- TextTrailingCharacterEllipsis.cs
- DataDocumentXPathNavigator.cs
- LineServices.cs
- _HTTPDateParse.cs
- XmlSchemaType.cs
- XmlConverter.cs
- MLangCodePageEncoding.cs
- ChannelAcceptor.cs
- MarginCollapsingState.cs
- BackgroundWorker.cs
- RowSpanVector.cs
- CodeExpressionCollection.cs
- HeaderPanel.cs
- XmlSchemaAttributeGroup.cs
- FormsAuthenticationCredentials.cs