Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / Statements / TransactionScope.cs / 1305376 / TransactionScope.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.Activities.Statements { using System; using System.Activities; using System.Activities.Validation; using System.Collections.Generic; using System.ComponentModel; using System.Runtime; using System.Transactions; using System.Windows.Markup; using System.Activities.Expressions; using System.Collections.ObjectModel; [ContentProperty("Body")] public sealed class TransactionScope : NativeActivity { const IsolationLevel defaultIsolationLevel = default(IsolationLevel); InArgumenttimeout; bool isTimeoutSetExplicitly; Variable runtimeTransactionHandle; bool abortInstanceOnTransactionFailure; bool abortInstanceFlagWasExplicitlySet; Delay nestedScopeTimeoutWorkflow; Variable delayWasScheduled; Variable nestedScopeTimeout; Variable nestedScopeTimeoutActivityInstance; static string runtimeTransactionHandlePropertyName = typeof(RuntimeTransactionHandle).FullName; const string AbortInstanceOnTransactionFailurePropertyName = "AbortInstanceOnTransactionFailure"; const string IsolationLevelPropertyName = "IsolationLevel"; const string BodyPropertyName = "Body"; public TransactionScope() : base() { this.timeout = new InArgument (TimeSpan.FromMinutes(1)); this.runtimeTransactionHandle = new Variable (); this.abortInstanceOnTransactionFailure = true; this.nestedScopeTimeout = new Variable (); this.delayWasScheduled = new Variable (); this.nestedScopeTimeoutActivityInstance = new Variable (); base.Constraints.Add(ProcessParentChainConstraints()); base.Constraints.Add(ProcessChildSubtreeConstraints()); } [DefaultValue(null)] public Activity Body { get; set; } [DefaultValue(true)] public bool AbortInstanceOnTransactionFailure { get { return this.abortInstanceOnTransactionFailure; } set { this.abortInstanceOnTransactionFailure = value; this.abortInstanceFlagWasExplicitlySet = true; } } public IsolationLevel IsolationLevel { get; set; } public InArgument Timeout { get { return this.timeout; } set { this.timeout = value; this.isTimeoutSetExplicitly = true; } } Delay NestedScopeTimeoutWorkflow { get { if (this.nestedScopeTimeoutWorkflow == null) { this.nestedScopeTimeoutWorkflow = new Delay { Duration = new InArgument (this.nestedScopeTimeout) }; } return this.nestedScopeTimeoutWorkflow; } } protected override bool CanInduceIdle { get { return true; } } [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeIsolationLevel() { return this.IsolationLevel != defaultIsolationLevel; } [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeTimeout() { return this.isTimeoutSetExplicitly; } protected override void CacheMetadata(NativeActivityMetadata metadata) { RuntimeArgument timeoutArgument = new RuntimeArgument("Timeout", typeof(TimeSpan), ArgumentDirection.In,false); metadata.Bind(this.Timeout, timeoutArgument); metadata.SetArgumentsCollection(new Collection { timeoutArgument }); metadata.AddImplementationChild(this.NestedScopeTimeoutWorkflow); if (this.Body != null) { metadata.AddChild(this.Body); } metadata.AddImplementationVariable(this.runtimeTransactionHandle); metadata.AddImplementationVariable(this.nestedScopeTimeout); metadata.AddImplementationVariable(this.delayWasScheduled); metadata.AddImplementationVariable(this.nestedScopeTimeoutActivityInstance); } Constraint ProcessParentChainConstraints() { DelegateInArgument element = new DelegateInArgument { Name = "element" }; DelegateInArgument validationContext = new DelegateInArgument { Name = "validationContext" }; DelegateInArgument parent = new DelegateInArgument { Name = "parent" }; return new Constraint { Body = new ActivityAction { Argument1 = element, Argument2 = validationContext, Handler = new Sequence { Activities = { new ForEach { Values = new GetParentChain { ValidationContext = validationContext, }, Body = new ActivityAction { Argument = parent, Handler = new Sequence { Activities = { new If() { Condition = new Equal { Left = new ObtainType { Input = parent, }, Right = new InArgument (context => typeof(TransactionScope)) }, Then = new Sequence { Activities = { new AssertValidation { IsWarning = true, Assertion = new AbortInstanceFlagValidator { ParentActivity = parent, TransactionScope = new InArgument (context => element.Get(context)) }, Message = new InArgument (SR.AbortInstanceOnTransactionFailureDoesNotMatch), PropertyName = AbortInstanceOnTransactionFailurePropertyName }, new AssertValidation { Assertion = new IsolationLevelValidator { ParentActivity = parent, CurrentIsolationLevel = new InArgument (context => element.Get(context).IsolationLevel) }, Message = new InArgument (SR.IsolationLevelValidation), PropertyName = IsolationLevelPropertyName } } } } } } } } } } } }; } Constraint ProcessChildSubtreeConstraints() { DelegateInArgument element = new DelegateInArgument { Name = "element" }; DelegateInArgument validationContext = new DelegateInArgument { Name = "validationContext" }; DelegateInArgument child = new DelegateInArgument { Name = "child" }; Variable nestedCompensableActivity = new Variable (); 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(CompensableActivity)) }, Then = new Assign { To = new OutArgument (nestedCompensableActivity), Value = new InArgument (true) } } } } } }, new AssertValidation() { Assertion = new InArgument (new Not { Operand = new VariableValue { Variable = nestedCompensableActivity }}), Message = new InArgument (SR.CompensableActivityInsideTransactionScopeActivity), PropertyName = BodyPropertyName } } } } }; } protected override void Execute(NativeActivityContext context) { RuntimeTransactionHandle transactionHandle = this.runtimeTransactionHandle.Get(context); Fx.Assert(transactionHandle != null, "RuntimeTransactionHandle is null"); RuntimeTransactionHandle foundHandle = context.Properties.Find(runtimeTransactionHandlePropertyName) as RuntimeTransactionHandle; if (foundHandle == null) { //Note, once the property is registered, we cannot change the state of this flag transactionHandle.AbortInstanceOnTransactionFailure = this.AbortInstanceOnTransactionFailure; context.Properties.Add(transactionHandle.ExecutionPropertyName, transactionHandle); } else { //nested case //foundHandle.IsRuntimeOwnedTransaction will be true only in the Invoke case within an ambient Sys.Tx transaction. //If this TSA is nested inside the ambient transaction from Invoke, then the AbortInstanceFlag is always false since the RTH corresponding to the ambient //transaction has this flag as false. In this case, we ignore if this TSA has this flag explicitly set to true. if(!foundHandle.IsRuntimeOwnedTransaction && this.abortInstanceFlagWasExplicitlySet && (foundHandle.AbortInstanceOnTransactionFailure != this.AbortInstanceOnTransactionFailure)) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.AbortInstanceOnTransactionFailureDoesNotMatch)); } if (foundHandle.SuppressTransaction) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CannotNestTransactionScopeWhenAmbientHandleIsSuppressed(this.DisplayName))); } transactionHandle = foundHandle; } Transaction transaction = transactionHandle.GetCurrentTransaction(context); //Check if there is already a transaction (Requires Semantics) if (transaction == null) { //If not, request one.. transactionHandle.RequestTransactionContext(context, OnContextAcquired, null); } else { //Most likely, you are inside a nested TSA if (transaction.IsolationLevel != this.IsolationLevel) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.IsolationLevelValidation)); } //Check if the nested TSA had a timeout specified explicitly if (this.isTimeoutSetExplicitly) { TimeSpan timeout = this.Timeout.Get(context); this.delayWasScheduled.Set(context, true); this.nestedScopeTimeout.Set(context, timeout); this.nestedScopeTimeoutActivityInstance.Set(context, context.ScheduleActivity(this.NestedScopeTimeoutWorkflow, new CompletionCallback(OnDelayCompletion))); } //execute the Body under the current runtime transaction ScheduleBody(context); } } void OnContextAcquired(NativeActivityTransactionContext context, object state) { Fx.Assert(context != null, "ActivityTransactionContext was null"); TimeSpan transactionTimeout = this.Timeout.Get(context); TransactionOptions transactionOptions = new TransactionOptions() { IsolationLevel = this.IsolationLevel, Timeout = transactionTimeout }; context.SetRuntimeTransaction(new CommittableTransaction(transactionOptions)); ScheduleBody(context); } void ScheduleBody(NativeActivityContext context) { if (this.Body != null) { context.ScheduleActivity(this.Body,new CompletionCallback(OnCompletion)); } } void OnCompletion(NativeActivityContext context, ActivityInstance instance) { RuntimeTransactionHandle transactionHandle = this.runtimeTransactionHandle.Get(context); Fx.Assert(transactionHandle != null, "RuntimeTransactionHandle is null"); if (this.delayWasScheduled.Get(context)) { transactionHandle.CompleteTransaction(context, new BookmarkCallback(OnTransactionComplete)); } else { transactionHandle.CompleteTransaction(context); } } void OnDelayCompletion(NativeActivityContext context, ActivityInstance instance) { if (instance.State == ActivityInstanceState.Closed) { RuntimeTransactionHandle handle = context.Properties.Find(runtimeTransactionHandlePropertyName) as RuntimeTransactionHandle; Fx.Assert(handle != null, "Internal error.. If we are here, there ought to be an ambient transaction handle"); handle.GetCurrentTransaction(context).Rollback(); } } void OnTransactionComplete(NativeActivityContext context, Bookmark bookmark, object state) { Fx.Assert(this.delayWasScheduled.Get(context), "Internal error..Delay should have been scheduled if we are here"); ActivityInstance delayActivityInstance = this.nestedScopeTimeoutActivityInstance.Get(context); if (delayActivityInstance != null) { context.CancelChild(delayActivityInstance); } } // class ObtainType : CodeActivity { public ObtainType() { } public InArgument Input { get; set; } protected override Type Execute(CodeActivityContext context) { return this.Input.Get(context).GetType(); } } class IsolationLevelValidator : CodeActivity { public InArgument ParentActivity { get; set; } public InArgument CurrentIsolationLevel { get; set; } protected override bool Execute(CodeActivityContext context) { Activity parent = this.ParentActivity.Get(context); if (parent != null) { TransactionScope transactionScope = parent as TransactionScope; Fx.Assert(transactionScope != null, "ParentActivity was not of expected type"); if (transactionScope.IsolationLevel != this.CurrentIsolationLevel.Get(context)) { return false; } else { return true; } } else { return true; } } } class AbortInstanceFlagValidator : CodeActivity { public InArgument ParentActivity { get; set; } public InArgument TransactionScope { get; set; } protected override bool Execute(CodeActivityContext context) { Activity parent = this.ParentActivity.Get(context); if (parent != null) { TransactionScope parentTransactionScope = parent as TransactionScope; Fx.Assert(parentTransactionScope != null, "ParentActivity was not of expected type"); TransactionScope currentTransactionScope = this.TransactionScope.Get(context); if (parentTransactionScope.AbortInstanceOnTransactionFailure != currentTransactionScope.AbortInstanceOnTransactionFailure) { //If the Inner TSA was default and still different from outer, we dont flag validation warning. See design spec for all variations if (!currentTransactionScope.abortInstanceFlagWasExplicitlySet) { return true; } else { return false; } } else { return true; } } else { 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
- DbProviderManifest.cs
- ToolboxItemFilterAttribute.cs
- ReferentialConstraint.cs
- TrackingStringDictionary.cs
- ScrollData.cs
- ProcessHostConfigUtils.cs
- JournalEntry.cs
- MemoryRecordBuffer.cs
- CompleteWizardStep.cs
- Preprocessor.cs
- DataGridViewMethods.cs
- LongAverageAggregationOperator.cs
- EventListener.cs
- GacUtil.cs
- ClipboardProcessor.cs
- WebServiceFault.cs
- ThousandthOfEmRealDoubles.cs
- BackgroundFormatInfo.cs
- HandlerMappingMemo.cs
- SpellerError.cs
- TransactionContextManager.cs
- SimpleRecyclingCache.cs
- SecurityHelper.cs
- ErrorWebPart.cs
- filewebresponse.cs
- ConfigXmlDocument.cs
- AdPostCacheSubstitution.cs
- XPathMessageFilterTable.cs
- UndoManager.cs
- TextEffect.cs
- ToolStripScrollButton.cs
- UIPermission.cs
- DataGrid.cs
- DefaultTraceListener.cs
- PeerPresenceInfo.cs
- DataListItem.cs
- EpmCustomContentDeSerializer.cs
- OdbcConnectionPoolProviderInfo.cs
- AttachedPropertyBrowsableAttribute.cs
- Logging.cs
- BridgeDataRecord.cs
- ParentQuery.cs
- TypeSystemHelpers.cs
- CodeStatement.cs
- CapabilitiesRule.cs
- COM2Enum.cs
- AtomParser.cs
- ReceiveReply.cs
- XpsSerializationManager.cs
- oledbmetadatacollectionnames.cs
- BamlResourceContent.cs
- Rotation3DAnimationBase.cs
- FontDifferentiator.cs
- RTTypeWrapper.cs
- XappLauncher.cs
- WebScriptEnablingBehavior.cs
- DataGridViewCellValueEventArgs.cs
- CodeStatementCollection.cs
- Encoding.cs
- PermissionRequestEvidence.cs
- DataControlLinkButton.cs
- TextComposition.cs
- TextDecorationCollectionConverter.cs
- TableSectionStyle.cs
- RelationshipConstraintValidator.cs
- TextHidden.cs
- ApplicationServiceHelper.cs
- AddInPipelineAttributes.cs
- CryptoProvider.cs
- StateMachineSubscriptionManager.cs
- SessionEndingEventArgs.cs
- StatusBar.cs
- OutputCacheSection.cs
- srgsitem.cs
- InkCanvasInnerCanvas.cs
- SafeLibraryHandle.cs
- DeploymentSection.cs
- DataServiceExpressionVisitor.cs
- PasswordBoxAutomationPeer.cs
- TextDecorationLocationValidation.cs
- WebControlParameterProxy.cs
- StringUtil.cs
- ShapeTypeface.cs
- OutputCacheSection.cs
- HtmlDocument.cs
- UMPAttributes.cs
- PersistChildrenAttribute.cs
- __ComObject.cs
- CodeParameterDeclarationExpression.cs
- SqlComparer.cs
- MetricEntry.cs
- Span.cs
- XmlSerializerAssemblyAttribute.cs
- TimeSpanMinutesOrInfiniteConverter.cs
- HttpRequestCacheValidator.cs
- UserPersonalizationStateInfo.cs
- XmlAnyAttributeAttribute.cs
- LocationReferenceEnvironment.cs
- XmlnsDefinitionAttribute.cs
- RepeaterDesigner.cs