Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Dispatcher / TransactionBehavior.cs / 1 / TransactionBehavior.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.ServiceModel.Dispatcher { using System; using System.ServiceModel; using System.ServiceModel.Channels; using System.Diagnostics; using System.ServiceModel.Diagnostics; using System.Collections.Generic; using System.Globalization; using System.Transactions; using System.ServiceModel.Transactions; using System.Runtime.Serialization; using System.Runtime.CompilerServices; using System.Web.Hosting; internal class TransactionBehavior { bool isConcurrent; IsolationLevel isolation = ServiceBehaviorAttribute.DefaultIsolationLevel; DispatchRuntime dispatch; TimeSpan timeout = TimeSpan.Zero; bool isTransactedReceiveChannelDispatcher = false; internal TransactionBehavior() { } internal TransactionBehavior(DispatchRuntime dispatch) { this.isConcurrent = (dispatch.ConcurrencyMode == ConcurrencyMode.Multiple || dispatch.ConcurrencyMode == ConcurrencyMode.Reentrant); this.dispatch = dispatch; this.isTransactedReceiveChannelDispatcher = dispatch.ChannelDispatcher.IsTransactedReceive; // Don't pull in System.Transactions.dll if we don't need it if (dispatch.ChannelDispatcher.TransactionIsolationLevelSet) this.InitializeIsolationLevel(dispatch); this.timeout = TransactionBehavior.NormalizeTimeout(dispatch.ChannelDispatcher.TransactionTimeout); } internal static Exception CreateFault(string reasonText, string codeString, bool isNetDispatcherFault) { string faultCodeNamespace, action; // 'Transactions' action should be used only when we expect to have a TransactionChannel in the channel stack // otherwise one should use the NetDispatch action. if (isNetDispatcherFault) { faultCodeNamespace = FaultCodeConstants.Namespaces.NetDispatch; action = FaultCodeConstants.Actions.NetDispatcher; } else { faultCodeNamespace = FaultCodeConstants.Namespaces.Transactions; action = FaultCodeConstants.Actions.Transactions; } FaultReason reason = new FaultReason(reasonText, CultureInfo.CurrentCulture); FaultCode code = FaultCode.CreateSenderFaultCode(codeString, faultCodeNamespace); return new FaultException(reason, code, action); } internal static TransactionBehavior CreateIfNeeded(DispatchRuntime dispatch) { if (TransactionBehavior.NeedsTransactionBehavior(dispatch)) { return new TransactionBehavior(dispatch); } else { return null; } } internal static TimeSpan NormalizeTimeout(TimeSpan timeout) { if (TimeSpan.Zero == timeout) { timeout = TransactionManager.DefaultTimeout; } else if (TimeSpan.Zero != TransactionManager.MaximumTimeout && timeout > TransactionManager.MaximumTimeout) { timeout = TransactionManager.MaximumTimeout; } return timeout; } internal static CommittableTransaction CreateTransaction(IsolationLevel isolation, TimeSpan timeout) { TransactionOptions options = new TransactionOptions(); options.IsolationLevel = isolation; options.Timeout = timeout; return new CommittableTransaction(options); } internal void SetCurrent(ref MessageRpc rpc) { if (!this.isConcurrent) { rpc.InstanceContext.Transaction.SetCurrent(ref rpc); } } internal void BeforeReply(ref MessageRpc rpc) { if ((rpc.InstanceContext != null) && (rpc.transaction != null)) { TransactionInstanceContextFacet context = rpc.InstanceContext.Transaction; if (context != null) { context.CheckIfTxCompletedAndUpdateAttached(ref rpc, this.isConcurrent); } rpc.Transaction.Complete(rpc.Error); } } Transaction GetInstanceContextTransaction(ref MessageRpc rpc) { return rpc.InstanceContext.Transaction.Attached; } [MethodImpl(MethodImplOptions.NoInlining)] void InitializeIsolationLevel(DispatchRuntime dispatch) { this.isolation = dispatch.ChannelDispatcher.TransactionIsolationLevel; } static bool NeedsTransactionBehavior(DispatchRuntime dispatch) { DispatchOperation unhandled = dispatch.UnhandledDispatchOperation; if ((unhandled != null) && (unhandled.TransactionRequired)) { return true; } if (dispatch.ChannelDispatcher.IsTransactedReceive) //check if we have transacted receive { return true; } for (int i = 0; i < dispatch.Operations.Count; i++) { DispatchOperation operation = dispatch.Operations[i]; if (operation.TransactionRequired) { return true; } } return false; } internal void ResolveTransaction(ref MessageRpc rpc) { if(rpc.Operation.HasDefaultUnhandledActionInvoker) { // we ignore unhandled operations return; } Transaction contextTransaction = this.GetInstanceContextTransaction(ref rpc); Transaction transaction = null; try { transaction = TransactionMessageProperty.TryGetTransaction(rpc.Request); } catch (TransactionException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionUnmarshalFailed, e.Message), FaultCodeConstants.Codes.TransactionUnmarshalingFailed, false)); } if (rpc.Operation.TransactionRequired) { if (transaction != null) { if(this.isTransactedReceiveChannelDispatcher) { if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredIsTransactedTransport, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsTransactedTransport, transaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } else { if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredIsTransactionFlow, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsTransactionFlow, transaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); if (PerformanceCounters.PerformanceCountersEnabled) { PerformanceCounters.TxFlowed(PerformanceCounters.GetEndpointDispatcher(), rpc.Operation.Name); } if(transaction != contextTransaction) { try { transaction = transaction.DependentClone(DependentCloneOption.RollbackIfNotComplete); } catch(TransactionException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } } } } } else { // We got a transaction from the ChannelHandler. // Transport is transacted. // But operation doesn't require the transaction, so no one ever will commit it. // Because of that we have to commit it here. if (transaction != null && this.isTransactedReceiveChannelDispatcher) { try { if (null != rpc.TransactedBatchContext) { rpc.TransactedBatchContext.ForceCommit(); rpc.TransactedBatchContext = null; } else { TransactionInstanceContextFacet.Complete(transaction, null); } } finally { transaction.Dispose(); transaction = null; } } } InstanceContext context = rpc.InstanceContext; if(context.Transaction.ShouldReleaseInstance && !this.isConcurrent) { if(context.Behavior.ReleaseServiceInstanceOnTransactionComplete) { context.ReleaseServiceInstance(); if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxReleaseServiceInstanceOnCompletion, SR.GetString(SR.TraceCodeTxReleaseServiceInstanceOnCompletion, contextTransaction.TransactionInformation.LocalIdentifier) ); } context.Transaction.ShouldReleaseInstance = false; if(transaction == null || transaction == contextTransaction) { rpc.Transaction.Current = contextTransaction; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } else { contextTransaction = null; } } if (rpc.Operation.TransactionRequired) { if (transaction == null) { if(contextTransaction != null) { transaction = contextTransaction; if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredIsAttachedTransaction, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsAttachedTransaction, transaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } else { transaction = TransactionBehavior.CreateTransaction(this.isolation, this.timeout); if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxSourceTxScopeRequiredIsCreateNewTransaction, SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsCreateNewTransaction, transaction.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } } if ((this.isolation != IsolationLevel.Unspecified) && (transaction.IsolationLevel != this.isolation)) { throw TraceUtility.ThrowHelperError(TransactionBehavior.CreateFault (SR.GetString(SR.IsolationLevelMismatch2, transaction.IsolationLevel, this.isolation), FaultCodeConstants.Codes.TransactionIsolationLevelMismatch, false), rpc.Request); } rpc.Transaction.Current = transaction; rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Current, true); try { rpc.Transaction.Clone = transaction.Clone(); } catch (ObjectDisposedException e)//transaction may be async aborted { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Clone, false); rpc.OperationContext.TransactionFacet = rpc.Transaction; if (!rpc.Operation.TransactionAutoComplete) { rpc.Transaction.SetIncomplete(); } } } internal void InitializeCallContext(ref MessageRpc rpc) { if (rpc.Operation.TransactionRequired) rpc.Transaction.ThreadEnter(ref rpc.Error); } internal void ClearCallContext(ref MessageRpc rpc) { if (rpc.Operation.TransactionRequired) rpc.Transaction.ThreadLeave(); } } internal class TransactionRpcFacet { //private members TransactionScope scope; bool transactionSetComplete = false; // To track if user has called SetTransactionComplete() //internal members // Current is the original transaction that we created/flowed/whatever. This is // the "current" transaction used by the operation, and we keep it around so we // can commit it, complete it, etc. // // Clone is a clone of Current. We keep it around to pass into TransactionScope // so that System.Transactions.Transaction.Current is not CommittableTransaction // or anything dangerous like that. internal Transaction Current; internal Transaction Clone; internal bool IsCompleted = true; internal MessageRpc rpc; internal TransactionRpcFacet() {} internal TransactionRpcFacet(ref MessageRpc rpc) { this.rpc = rpc; } // Calling Complete will Commit or Abort the transaction based on, // error - If any user error is propagated to the service we abort the transaction unless SetTransactionComplete was successful. // transactionDoomed - If internal error occurred and this error may or may not be propagated // by the user to the service. Abort the Tx if transactionDoomed is set true. // // If the user violates the following rules, the transaction is doomed. // User cannot call TransactionSetComplete() when TransactionAutoComplete is true. // User cannot call TransactionSetComplete() multiple times. [MethodImpl(MethodImplOptions.NoInlining)] internal void Complete(Exception error) { if (!object.ReferenceEquals(this.Current, null)) { TransactedBatchContext batchContext = this.rpc.TransactedBatchContext; if (null != batchContext) { if (null == error) batchContext.Complete(); else batchContext.ForceRollback(); batchContext.InDispatch = false; } else { if(this.transactionSetComplete) { // Commit the transaction when TransactionSetComplete() is called and // even when an exception(non transactional) happens after this call. rpc.InstanceContext.Transaction.CompletePendingTransaction(this.Current, null); if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxCompletionStatusCompletedForSetComplete, SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForSetComplete, this.Current.TransactionInformation.LocalIdentifier, this.rpc.Operation.Name) ); } else if(this.IsCompleted || (error != null)) { rpc.InstanceContext.Transaction.CompletePendingTransaction(this.Current, error); } } this.Current = null; } } internal void SetIncomplete() { this.IsCompleted = false; } internal void Completed() { if(this.scope == null) return; // Prohibit user from calling SetTransactionComplete() when TransactionAutoComplete is set to true. // Transaction will be aborted. if(this.rpc.Operation.TransactionAutoComplete) { try { this.Current.Rollback(); } catch(ObjectDisposedException e) { //we don't want to mask the real error here DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.GetString(SR.SFxTransactionInvalidSetTransactionComplete, rpc.Operation.Name, rpc.Host.Description.Name))); } // Prohibit user from calling SetTransactionComplete() multiple times. // Transaction will be aborted. else if(this.transactionSetComplete) { try { this.Current.Rollback(); } catch(ObjectDisposedException e) { //we don't want to mask the real error here DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.GetString(SR.SFxMultiSetTransactionComplete, rpc.Operation.Name, rpc.Host.Description.Name))); } this.transactionSetComplete = true; this.IsCompleted = true; this.scope.Complete(); } [MethodImpl(MethodImplOptions.NoInlining)] internal void ThreadEnter(ref Exception error) { Transaction clone = this.Clone; if ((clone != null) && (error == null)) { this.scope = this.rpc.InstanceContext.Transaction.CreateTransactionScope(clone); this.transactionSetComplete = false; } } [MethodImpl(MethodImplOptions.NoInlining)] internal void ThreadLeave() { if(this.scope != null) { if (!this.transactionSetComplete) { this.scope.Complete(); } try { this.scope.Dispose(); return; } catch (TransactionException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } } } } internal sealed class TransactionInstanceContextFacet { IResumeMessageRpc paused; // the IResumeMessageRpc for this.waiting. object mutex; Transaction current; // the one true transaction when Concurrency=false. InstanceContext instanceContext; Dictionarypending; // When Concurrency=true, all the still pending guys. internal Transaction waiting; // waiting to become Single because Single is on his way out. bool shouldReleaseInstance = false; internal Transaction Attached; internal TransactionInstanceContextFacet(InstanceContext instanceContext) { this.instanceContext = instanceContext; this.mutex = instanceContext.ThisLock; } // ........................................................................................................ // no need to lock the following property because it's used only if Concurrency = false internal bool ShouldReleaseInstance { get { return this.shouldReleaseInstance; } set { this.shouldReleaseInstance = value; } } // ........................................................................................................ [MethodImpl(MethodImplOptions.NoInlining)] internal void CheckIfTxCompletedAndUpdateAttached(ref MessageRpc rpc, bool isConcurrent) { if(rpc.Transaction.Current == null) return; lock(this.mutex) { if (!isConcurrent) { if(this.shouldReleaseInstance) { this.shouldReleaseInstance = false; if(rpc.Error == null) //we don't want to mask the initial error { rpc.Error = TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true); DiagnosticUtility.ExceptionUtility.TraceHandledException(rpc.Error, TraceEventType.Error); if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxCompletionStatusCompletedForAsyncAbort, SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAsyncAbort, rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } } if (rpc.Transaction.IsCompleted || (rpc.Error != null)) { if(DiagnosticUtility.ShouldTraceInformation) { if(rpc.Error != null) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxCompletionStatusCompletedForError, SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForError, rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); else DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxCompletionStatusCompletedForAutocomplete, SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAutocomplete, rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } this.Attached = null; if (!(waiting == null)) { // tx processing requires failfast when state is inconsistent DiagnosticUtility.FailFast("waiting should be null when resetting current"); } this.current = null; } else { this.Attached = rpc.Transaction.Current; if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxCompletionStatusRemainsAttached, SR.GetString(SR.TraceCodeTxCompletionStatusRemainsAttached, rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } } else if(!this.pending.ContainsKey(rpc.Transaction.Current)) { //transaction has been asynchronously aborted if(rpc.Error == null) //we don't want to mask the initial error { rpc.Error = TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true); DiagnosticUtility.ExceptionUtility.TraceHandledException(rpc.Error, TraceEventType.Error); if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxCompletionStatusCompletedForAsyncAbort, SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAsyncAbort, rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name) ); } } } } // ........................................................................................................ internal void CompletePendingTransaction(Transaction transaction, Exception error) { lock(this.mutex) { if(this.pending.ContainsKey(transaction)) { Complete(transaction, error); } } } // ........................................................................................................ internal static void Complete(Transaction transaction, Exception error) { try { if (error == null) { CommittableTransaction commit = (transaction as CommittableTransaction); if (commit != null) { commit.Commit(); } else { DependentTransaction complete = (transaction as DependentTransaction); if (complete != null) { complete.Complete(); } } } else { transaction.Rollback(); } } catch (TransactionException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } } // ........................................................................................................ internal TransactionScope CreateTransactionScope(Transaction transaction) { lock(this.mutex) { if(this.pending.ContainsKey(transaction)) { try { return new TransactionScope(transaction); } catch (TransactionException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); //we'll rethrow below } } } //the transaction was asynchronously aborted throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true)); } // ........................................................................................................ internal void SetCurrent(ref MessageRpc rpc) { Transaction requestTransaction = rpc.Transaction.Current; if (!(requestTransaction != null)) { // tx processing requires failfast when state is inconsistent DiagnosticUtility.FailFast("we should never get here with a requestTransaction null"); } lock(this.mutex) { if(this.current == null) { this.current = requestTransaction; } else if(this.current != requestTransaction) { this.waiting = requestTransaction; this.paused = rpc.Pause(); } else { rpc.Transaction.Current = this.current; //rpc.Transaction.Current should get the dependent clone } } } // ........................................................................................................ internal void AddReference(ref MessageRpc rpc, Transaction tx, bool updateCallCount) { lock (this.mutex) { if (this.pending == null) { this.pending = new Dictionary (); } if (tx != null) { if (this.pending == null) this.pending = new Dictionary (); RemoveReferenceRM rm; if (!this.pending.TryGetValue(tx, out rm)) { RemoveReferenceRM rrm = new RemoveReferenceRM(this.instanceContext, tx, rpc.Operation.Name); rrm.CallCount = 1; this.pending.Add(tx, rrm); } else if (updateCallCount) { rm.CallCount += 1; } } } } internal void RemoveReference(Transaction tx) { lock (this.mutex) { if(tx.Equals(this.current)) { if(this.waiting != null) { this.current = waiting; this.waiting = null; if(instanceContext.Behavior.ReleaseServiceInstanceOnTransactionComplete) { instanceContext.ReleaseServiceInstance(); if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxReleaseServiceInstanceOnCompletion, SR.GetString(SR.TraceCodeTxReleaseServiceInstanceOnCompletion, tx.TransactionInformation.LocalIdentifier) ); } bool alreadyResumedNoLock; this.paused.Resume(out alreadyResumedNoLock); if (alreadyResumedNoLock) { DiagnosticUtility.DebugAssert("TransactionBehavior resumed more than once for same call."); } } else { this.shouldReleaseInstance = true; this.current = null; } } if (this.pending != null) { if (this.pending.ContainsKey(tx)) { this.pending.Remove(tx); } } } } // ........................................................................................................ abstract class VolatileBase : ISinglePhaseNotification { protected InstanceContext InstanceContext; protected Transaction Transaction; protected VolatileBase(InstanceContext instanceContext, Transaction transaction) { this.InstanceContext = instanceContext; this.Transaction = transaction; this.Transaction.EnlistVolatile(this, EnlistmentOptions.None); } protected abstract void Completed(); public virtual void Commit(Enlistment enlistment) { this.Completed(); } public virtual void InDoubt(Enlistment enlistment) { this.Completed(); } public virtual void Rollback(Enlistment enlistment) { this.Completed(); } public virtual void SinglePhaseCommit(SinglePhaseEnlistment enlistment) { enlistment.Committed(); this.Completed(); } public void Prepare(PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); } } sealed class RemoveReferenceRM : VolatileBase { string operation; long callCount = 0; EndpointDispatcher endpointDispatcher; internal RemoveReferenceRM(InstanceContext instanceContext, Transaction tx, string operation) : base(instanceContext, tx) { this.operation = operation; if (PerformanceCounters.PerformanceCountersEnabled) { this.endpointDispatcher = PerformanceCounters.GetEndpointDispatcher(); } ServiceHostingEnvironment.IncrementBusyCount(); } internal long CallCount { get { return this.callCount; } set { this.callCount = value; } } protected override void Completed() { this.InstanceContext.Transaction.RemoveReference(this.Transaction); ServiceHostingEnvironment.DecrementBusyCount(); } public override void SinglePhaseCommit(SinglePhaseEnlistment enlistment) { if (PerformanceCounters.PerformanceCountersEnabled) { PerformanceCounters.TxCommitted(this.endpointDispatcher, CallCount); } base.SinglePhaseCommit(enlistment); } public override void Commit(Enlistment enlistment) { if (PerformanceCounters.PerformanceCountersEnabled) { PerformanceCounters.TxCommitted(this.endpointDispatcher, CallCount); } base.Commit(enlistment); } public override void Rollback(Enlistment enlistment) { if (PerformanceCounters.PerformanceCountersEnabled) { PerformanceCounters.TxAborted(this.endpointDispatcher, CallCount); } if(DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxAsyncAbort, SR.GetString(SR.TraceCodeTxAsyncAbort, this.Transaction.TransactionInformation.LocalIdentifier) ); base.Rollback(enlistment); } public override void InDoubt(Enlistment enlistment) { if (PerformanceCounters.PerformanceCountersEnabled) { PerformanceCounters.TxInDoubt(this.endpointDispatcher, CallCount); } base.InDoubt(enlistment); } } } internal enum ExclusiveInstanceContextTransactionResult { Acquired, Wait, Fault }; } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DetailsViewRow.cs
- RuntimeEnvironment.cs
- ThemeInfoAttribute.cs
- XmlILTrace.cs
- CopyEncoder.cs
- TreeNodeStyleCollection.cs
- SQLInt32Storage.cs
- ContainerControl.cs
- DataContractSerializerSection.cs
- HtmlInputReset.cs
- BaseCAMarshaler.cs
- CircleHotSpot.cs
- CellPartitioner.cs
- AngleUtil.cs
- NonParentingControl.cs
- SafeNativeMethods.cs
- MULTI_QI.cs
- SqlIdentifier.cs
- InstanceDataCollection.cs
- EncoderExceptionFallback.cs
- TimeStampChecker.cs
- TagNameToTypeMapper.cs
- RuleInfoComparer.cs
- _Semaphore.cs
- StandardTransformFactory.cs
- RegistrationServices.cs
- Span.cs
- ListViewHitTestInfo.cs
- FormsAuthentication.cs
- HotCommands.cs
- XmlSerializationWriter.cs
- InternalException.cs
- TabRenderer.cs
- HtmlHistory.cs
- XmlObjectSerializerWriteContextComplexJson.cs
- LinqExpressionNormalizer.cs
- DynamicResourceExtension.cs
- Button.cs
- ProcessThreadDesigner.cs
- RelationshipDetailsRow.cs
- QilTypeChecker.cs
- Keyboard.cs
- MetadataItem_Static.cs
- Propagator.Evaluator.cs
- WebPartExportVerb.cs
- ContentPlaceHolder.cs
- ExpandSegment.cs
- BuildResult.cs
- documentsequencetextview.cs
- RenderContext.cs
- TextBox.cs
- SchemaObjectWriter.cs
- WebPartDisplayModeCancelEventArgs.cs
- FieldBuilder.cs
- ZipIOExtraFieldElement.cs
- DynamicResourceExtensionConverter.cs
- FixedTextSelectionProcessor.cs
- LicenseContext.cs
- DataServiceQueryOfT.cs
- AppModelKnownContentFactory.cs
- ObjectView.cs
- QilGeneratorEnv.cs
- ECDsaCng.cs
- ObjectQuery.cs
- LambdaExpression.cs
- ProgressBar.cs
- OleDbReferenceCollection.cs
- FormattedText.cs
- WindowsGraphicsWrapper.cs
- _RequestLifetimeSetter.cs
- _SafeNetHandles.cs
- DbTransaction.cs
- Debug.cs
- XmlSchemaAnnotation.cs
- TemplateModeChangedEventArgs.cs
- SqlConnectionStringBuilder.cs
- ConfigUtil.cs
- WebControlAdapter.cs
- ToolStripItemEventArgs.cs
- WindowsFormsSynchronizationContext.cs
- TimeZoneNotFoundException.cs
- ClipboardProcessor.cs
- DefaultAsyncDataDispatcher.cs
- AsnEncodedData.cs
- ArgumentReference.cs
- PropertiesTab.cs
- ResourceExpressionEditorSheet.cs
- ContainerActivationHelper.cs
- ObjectParameter.cs
- DocumentApplicationJournalEntry.cs
- RegexWorker.cs
- DriveInfo.cs
- Funcletizer.cs
- ConnectionProviderAttribute.cs
- DocumentViewerHelper.cs
- WebPartZone.cs
- StructuredTypeEmitter.cs
- WebPartConnectVerb.cs
- PageParser.cs
- XNodeNavigator.cs