Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / RunTime / Hosting / SharedConnectionWorkflowTransactionService.cs / 1305376 / SharedConnectionWorkflowTransactionService.cs
#pragma warning disable 1634, 1691 //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- #region Using directives using System; using System.Transactions; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; using System.Threading; #endregion namespace System.Workflow.Runtime.Hosting { public class SharedConnectionWorkflowCommitWorkBatchService : WorkflowCommitWorkBatchService { private DbResourceAllocator dbResourceAllocator; private IDictionarytransactionConnectionTable; private object tableSyncObject = new object(); // Saved from constructor input to be used in service start initialization private NameValueCollection configParameters; string unvalidatedConnectionString; private bool _enableRetries = false; private bool _ignoreCommonEnableRetries = false; /// /// Enables the adding of this service programmatically. /// /// /// public SharedConnectionWorkflowCommitWorkBatchService(string connectionString) { if (String.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString", ExecutionStringManager.MissingConnectionString); this.unvalidatedConnectionString = connectionString; } ////// Enables adding of this service from a config file. /// Get the connection string from the runtime common parameter section or the particular service parameter section /// of the configuration file, and instantiate a DbResourceAllocator object. /// /// /// public SharedConnectionWorkflowCommitWorkBatchService(NameValueCollection parameters) { if (parameters == null) throw new ArgumentNullException("parameters", ExecutionStringManager.MissingParameters); if (parameters.Count > 0) { foreach (string key in parameters.Keys) { if (0 == string.Compare("EnableRetries", key, StringComparison.OrdinalIgnoreCase)) { _enableRetries = bool.Parse(parameters[key]); _ignoreCommonEnableRetries = true; } } } this.configParameters = parameters; } #region Accessors internal string ConnectionString { get { #pragma warning disable 56503 if (this.dbResourceAllocator == null) { // Other hosting services may try to get the connection string during their initialization phase // (in WorkflowRuntimeService.Start) to dectect string mismatch conflict if (this.Runtime == null) throw new InvalidOperationException(ExecutionStringManager.WorkflowRuntimeNotStarted); this.dbResourceAllocator = new DbResourceAllocator(this.Runtime, this.configParameters, this.unvalidatedConnectionString); } #pragma warning restore 56503 return this.dbResourceAllocator.ConnectionString; } } public bool EnableRetries { get { return _enableRetries; } set { _enableRetries = value; _ignoreCommonEnableRetries = true; } } #endregion Accessors #region WorkflowRuntimeService override protected internal void Start() { WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SharedConnectionWorkflowCommitWorkBatchService: Starting"); this.dbResourceAllocator = new DbResourceAllocator(this.Runtime, this.configParameters, this.unvalidatedConnectionString); if (this.transactionConnectionTable == null) this.transactionConnectionTable = new Dictionary(); // // If we didn't find a local value for enable retries // check in the common section if ((!_ignoreCommonEnableRetries) && (null != base.Runtime)) { NameValueConfigurationCollection commonConfigurationParameters = base.Runtime.CommonParameters; if (commonConfigurationParameters != null) { // Then scan for connection string in the common configuration parameters section foreach (string key in commonConfigurationParameters.AllKeys) { if (string.Compare("EnableRetries", key, StringComparison.OrdinalIgnoreCase) == 0) { _enableRetries = bool.Parse(commonConfigurationParameters[key].Value); break; } } } } base.Start(); } protected override void OnStopped() { WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SharedConnectionWorkflowCommitWorkBatchService: Stopping"); foreach (KeyValuePair kvp in this.transactionConnectionTable) { kvp.Value.Dispose(); WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "Removing transaction " + kvp.Key.GetHashCode()); } this.transactionConnectionTable.Clear(); this.dbResourceAllocator = null; base.OnStopped(); } #endregion Public Methods #region Public Methods protected internal override void CommitWorkBatch(WorkflowCommitWorkBatchService.CommitWorkBatchCallback commitWorkBatchCallback) { // // Disable retries by default, reset to allow retries below if we own the tx DbRetry dbRetry = new DbRetry(_enableRetries); short retryCounter = dbRetry.MaxRetries; while (true) { // // When using LocalTransaction handle block access to the connection // in the transaction event handlers until all IPendingWork members have completed ManualResetEvent handle = new ManualResetEvent(false); Transaction tx = null; SharedConnectionInfo connectionInfo = null; try { if (null == Transaction.Current) { // // It's OK to retry here as we own the tx retryCounter = 0; // // Create a local, non promotable transaction that we share with our OOB services tx = new CommittableTransaction(); connectionInfo = new SharedConnectionInfo(this.dbResourceAllocator, tx, false, handle); } else { // // Can't retry as we don't own the tx // Create a dependent transaction and don't restrict promotion. tx = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete); connectionInfo = new SharedConnectionInfo(this.dbResourceAllocator, tx, true, handle); } AddToConnectionInfoTable(tx, connectionInfo); using (TransactionScope ts = new TransactionScope(tx)) { try { commitWorkBatchCallback(); ts.Complete(); } finally { RemoveConnectionFromInfoTable(tx); // // Unblock transaction event handlers handle.Set(); } } CommittableTransaction committableTransaction = tx as CommittableTransaction; if (committableTransaction != null) committableTransaction.Commit(); DependentTransaction dependentTransaction = tx as DependentTransaction; if (dependentTransaction != null) dependentTransaction.Complete(); break; } catch (Exception e) { tx.Rollback(); WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "SharedConnectionWorkflowCommitWorkBatchService caught exception from commitWorkBatchCallback: " + e.ToString()); if (dbRetry.TryDoRetry(ref retryCounter)) { WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SharedConnectionWorkflowCommitWorkBatchService retrying commitWorkBatchCallback (retry attempt " + retryCounter.ToString(System.Globalization.CultureInfo.InvariantCulture) + ")"); continue; } else throw; } finally { handle.Close(); if (tx != null) { tx.Dispose(); } } } } /// /// Get the SharedConnectionInfo object from the hashtable keyed by the transaction /// /// ///internal SharedConnectionInfo GetConnectionInfo(Transaction transaction) { return LookupConnectionInfoTable(transaction); } #endregion Public Methods #region Private Methods private void RemoveConnectionFromInfoTable(Transaction transaction) { lock (this.tableSyncObject) { SharedConnectionInfo connectionInfo; WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "TransactionCompleted " + transaction.GetHashCode()); if (transactionConnectionTable.TryGetValue(transaction, out connectionInfo)) { connectionInfo.Dispose(); this.transactionConnectionTable.Remove(transaction); } else { WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "TransactionCompleted " + transaction.GetHashCode() + " not found in table of count " + this.transactionConnectionTable.Count); } } } private void AddToConnectionInfoTable(Transaction transaction, SharedConnectionInfo connectionInfo) { lock (this.tableSyncObject) { this.transactionConnectionTable.Add(transaction, connectionInfo); WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "AddToConnectionInfoTable " + transaction.GetHashCode() + " in table of count " + this.transactionConnectionTable.Count); } } private SharedConnectionInfo LookupConnectionInfoTable(Transaction transaction) { lock (this.tableSyncObject) { return transactionConnectionTable[transaction]; } } #endregion Private Methods } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. #pragma warning disable 1634, 1691 //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- #region Using directives using System; using System.Transactions; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; using System.Threading; #endregion namespace System.Workflow.Runtime.Hosting { public class SharedConnectionWorkflowCommitWorkBatchService : WorkflowCommitWorkBatchService { private DbResourceAllocator dbResourceAllocator; private IDictionarytransactionConnectionTable; private object tableSyncObject = new object(); // Saved from constructor input to be used in service start initialization private NameValueCollection configParameters; string unvalidatedConnectionString; private bool _enableRetries = false; private bool _ignoreCommonEnableRetries = false; /// /// Enables the adding of this service programmatically. /// /// /// public SharedConnectionWorkflowCommitWorkBatchService(string connectionString) { if (String.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString", ExecutionStringManager.MissingConnectionString); this.unvalidatedConnectionString = connectionString; } ////// Enables adding of this service from a config file. /// Get the connection string from the runtime common parameter section or the particular service parameter section /// of the configuration file, and instantiate a DbResourceAllocator object. /// /// /// public SharedConnectionWorkflowCommitWorkBatchService(NameValueCollection parameters) { if (parameters == null) throw new ArgumentNullException("parameters", ExecutionStringManager.MissingParameters); if (parameters.Count > 0) { foreach (string key in parameters.Keys) { if (0 == string.Compare("EnableRetries", key, StringComparison.OrdinalIgnoreCase)) { _enableRetries = bool.Parse(parameters[key]); _ignoreCommonEnableRetries = true; } } } this.configParameters = parameters; } #region Accessors internal string ConnectionString { get { #pragma warning disable 56503 if (this.dbResourceAllocator == null) { // Other hosting services may try to get the connection string during their initialization phase // (in WorkflowRuntimeService.Start) to dectect string mismatch conflict if (this.Runtime == null) throw new InvalidOperationException(ExecutionStringManager.WorkflowRuntimeNotStarted); this.dbResourceAllocator = new DbResourceAllocator(this.Runtime, this.configParameters, this.unvalidatedConnectionString); } #pragma warning restore 56503 return this.dbResourceAllocator.ConnectionString; } } public bool EnableRetries { get { return _enableRetries; } set { _enableRetries = value; _ignoreCommonEnableRetries = true; } } #endregion Accessors #region WorkflowRuntimeService override protected internal void Start() { WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SharedConnectionWorkflowCommitWorkBatchService: Starting"); this.dbResourceAllocator = new DbResourceAllocator(this.Runtime, this.configParameters, this.unvalidatedConnectionString); if (this.transactionConnectionTable == null) this.transactionConnectionTable = new Dictionary(); // // If we didn't find a local value for enable retries // check in the common section if ((!_ignoreCommonEnableRetries) && (null != base.Runtime)) { NameValueConfigurationCollection commonConfigurationParameters = base.Runtime.CommonParameters; if (commonConfigurationParameters != null) { // Then scan for connection string in the common configuration parameters section foreach (string key in commonConfigurationParameters.AllKeys) { if (string.Compare("EnableRetries", key, StringComparison.OrdinalIgnoreCase) == 0) { _enableRetries = bool.Parse(commonConfigurationParameters[key].Value); break; } } } } base.Start(); } protected override void OnStopped() { WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SharedConnectionWorkflowCommitWorkBatchService: Stopping"); foreach (KeyValuePair kvp in this.transactionConnectionTable) { kvp.Value.Dispose(); WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "Removing transaction " + kvp.Key.GetHashCode()); } this.transactionConnectionTable.Clear(); this.dbResourceAllocator = null; base.OnStopped(); } #endregion Public Methods #region Public Methods protected internal override void CommitWorkBatch(WorkflowCommitWorkBatchService.CommitWorkBatchCallback commitWorkBatchCallback) { // // Disable retries by default, reset to allow retries below if we own the tx DbRetry dbRetry = new DbRetry(_enableRetries); short retryCounter = dbRetry.MaxRetries; while (true) { // // When using LocalTransaction handle block access to the connection // in the transaction event handlers until all IPendingWork members have completed ManualResetEvent handle = new ManualResetEvent(false); Transaction tx = null; SharedConnectionInfo connectionInfo = null; try { if (null == Transaction.Current) { // // It's OK to retry here as we own the tx retryCounter = 0; // // Create a local, non promotable transaction that we share with our OOB services tx = new CommittableTransaction(); connectionInfo = new SharedConnectionInfo(this.dbResourceAllocator, tx, false, handle); } else { // // Can't retry as we don't own the tx // Create a dependent transaction and don't restrict promotion. tx = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete); connectionInfo = new SharedConnectionInfo(this.dbResourceAllocator, tx, true, handle); } AddToConnectionInfoTable(tx, connectionInfo); using (TransactionScope ts = new TransactionScope(tx)) { try { commitWorkBatchCallback(); ts.Complete(); } finally { RemoveConnectionFromInfoTable(tx); // // Unblock transaction event handlers handle.Set(); } } CommittableTransaction committableTransaction = tx as CommittableTransaction; if (committableTransaction != null) committableTransaction.Commit(); DependentTransaction dependentTransaction = tx as DependentTransaction; if (dependentTransaction != null) dependentTransaction.Complete(); break; } catch (Exception e) { tx.Rollback(); WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "SharedConnectionWorkflowCommitWorkBatchService caught exception from commitWorkBatchCallback: " + e.ToString()); if (dbRetry.TryDoRetry(ref retryCounter)) { WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SharedConnectionWorkflowCommitWorkBatchService retrying commitWorkBatchCallback (retry attempt " + retryCounter.ToString(System.Globalization.CultureInfo.InvariantCulture) + ")"); continue; } else throw; } finally { handle.Close(); if (tx != null) { tx.Dispose(); } } } } /// /// Get the SharedConnectionInfo object from the hashtable keyed by the transaction /// /// ///internal SharedConnectionInfo GetConnectionInfo(Transaction transaction) { return LookupConnectionInfoTable(transaction); } #endregion Public Methods #region Private Methods private void RemoveConnectionFromInfoTable(Transaction transaction) { lock (this.tableSyncObject) { SharedConnectionInfo connectionInfo; WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "TransactionCompleted " + transaction.GetHashCode()); if (transactionConnectionTable.TryGetValue(transaction, out connectionInfo)) { connectionInfo.Dispose(); this.transactionConnectionTable.Remove(transaction); } else { WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "TransactionCompleted " + transaction.GetHashCode() + " not found in table of count " + this.transactionConnectionTable.Count); } } } private void AddToConnectionInfoTable(Transaction transaction, SharedConnectionInfo connectionInfo) { lock (this.tableSyncObject) { this.transactionConnectionTable.Add(transaction, connectionInfo); WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "AddToConnectionInfoTable " + transaction.GetHashCode() + " in table of count " + this.transactionConnectionTable.Count); } } private SharedConnectionInfo LookupConnectionInfoTable(Transaction transaction) { lock (this.tableSyncObject) { return transactionConnectionTable[transaction]; } } #endregion Private Methods } } // 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
- FrameworkElementFactoryMarkupObject.cs
- ConfigurationValidatorAttribute.cs
- QueryContinueDragEventArgs.cs
- Rfc2898DeriveBytes.cs
- DataBindEngine.cs
- Cursor.cs
- CompilerScope.Storage.cs
- TextRenderer.cs
- ProfilePropertySettings.cs
- ConfigurationStrings.cs
- PropertyValue.cs
- KnownColorTable.cs
- SiteMapHierarchicalDataSourceView.cs
- UpdateTracker.cs
- MgmtConfigurationRecord.cs
- DocComment.cs
- CharAnimationUsingKeyFrames.cs
- UpdateManifestForBrowserApplication.cs
- Html32TextWriter.cs
- MetricEntry.cs
- NativeMethods.cs
- AttachedProperty.cs
- RuntimeIdentifierPropertyAttribute.cs
- ADMembershipUser.cs
- ButtonChrome.cs
- ClassicBorderDecorator.cs
- RtType.cs
- CommonXSendMessage.cs
- NetSectionGroup.cs
- PageContentCollection.cs
- XPathQilFactory.cs
- DataProtection.cs
- SqlInternalConnectionSmi.cs
- CompatibleComparer.cs
- ArrayWithOffset.cs
- BackStopAuthenticationModule.cs
- Vector3DAnimation.cs
- WindowsTitleBar.cs
- DetailsViewInsertEventArgs.cs
- Converter.cs
- AnnotationDocumentPaginator.cs
- StoreAnnotationsMap.cs
- SafeReversePInvokeHandle.cs
- ExpressionList.cs
- Int16AnimationBase.cs
- DBSqlParserTable.cs
- _AcceptOverlappedAsyncResult.cs
- XmlObjectSerializerWriteContext.cs
- Environment.cs
- ViewStateModeByIdAttribute.cs
- MultiSelectRootGridEntry.cs
- RichTextBox.cs
- SemaphoreSlim.cs
- DataGridViewRowHeaderCell.cs
- HttpResponseHeader.cs
- MetadataArtifactLoaderFile.cs
- storepermissionattribute.cs
- COM2ColorConverter.cs
- HasActivatableWorkflowEvent.cs
- MatrixConverter.cs
- IdleTimeoutMonitor.cs
- SystemWebSectionGroup.cs
- SerialStream.cs
- ProfileService.cs
- GridViewColumnCollectionChangedEventArgs.cs
- DataSvcMapFile.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- SortDescription.cs
- SrgsRulesCollection.cs
- Parameter.cs
- AddInAdapter.cs
- PagePropertiesChangingEventArgs.cs
- StylusPointPropertyInfo.cs
- DateTime.cs
- OperandQuery.cs
- Psha1DerivedKeyGenerator.cs
- RequestBringIntoViewEventArgs.cs
- DelegatedStream.cs
- PersistenceContext.cs
- DataGridViewDataConnection.cs
- BitmapEffectInput.cs
- GeneralTransform2DTo3DTo2D.cs
- Site.cs
- WindowsGraphics2.cs
- EnumerableCollectionView.cs
- InsufficientMemoryException.cs
- DetailsViewDeletedEventArgs.cs
- XmlSignatureManifest.cs
- XmlLoader.cs
- ElementsClipboardData.cs
- AudioFormatConverter.cs
- QilExpression.cs
- TransformedBitmap.cs
- ISAPIRuntime.cs
- parserscommon.cs
- SiteMapDataSource.cs
- HMACRIPEMD160.cs
- HandlerElementCollection.cs
- TrailingSpaceComparer.cs
- GenericTypeParameterBuilder.cs