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
- XmlSchemaValidator.cs
- ScriptingRoleServiceSection.cs
- NotifyInputEventArgs.cs
- ModuleBuilderData.cs
- HyperLinkColumn.cs
- XmlSignatureProperties.cs
- OleDbConnectionFactory.cs
- DataGridPageChangedEventArgs.cs
- FontFaceLayoutInfo.cs
- WindowsPrincipal.cs
- ModifierKeysValueSerializer.cs
- PropertyInformation.cs
- ReflectionServiceProvider.cs
- DataSourceView.cs
- XmlComment.cs
- GlyphElement.cs
- BaseCollection.cs
- DbConnectionPoolOptions.cs
- SharedUtils.cs
- ValidationEventArgs.cs
- ErrorWrapper.cs
- _ConnectOverlappedAsyncResult.cs
- StateDesigner.LayoutSelectionGlyph.cs
- LocatorManager.cs
- InvalidOleVariantTypeException.cs
- SlotInfo.cs
- InkCanvasAutomationPeer.cs
- SpeechUI.cs
- EncryptedData.cs
- ProtectedConfigurationSection.cs
- Form.cs
- ParallelEnumerable.cs
- GridLengthConverter.cs
- SQLDecimalStorage.cs
- AutomationElement.cs
- DataSourceDescriptorCollection.cs
- TextElementEnumerator.cs
- codemethodreferenceexpression.cs
- FontStyle.cs
- ServiceModelEnumValidatorAttribute.cs
- TransportSecurityBindingElement.cs
- DbParameterHelper.cs
- CustomValidator.cs
- SapiGrammar.cs
- ToolboxBitmapAttribute.cs
- HintTextMaxWidthConverter.cs
- PipelineDeploymentState.cs
- EnlistmentState.cs
- Pair.cs
- XPathScanner.cs
- ImageClickEventArgs.cs
- InvokeMethod.cs
- XmlSchemaCompilationSettings.cs
- VectorCollectionConverter.cs
- MetadataItem.cs
- DataGridViewSortCompareEventArgs.cs
- PathNode.cs
- HttpProfileBase.cs
- SymbolEqualComparer.cs
- Point4DValueSerializer.cs
- StructuredTypeEmitter.cs
- ExpressionParser.cs
- MessageQueuePermission.cs
- IdentityManager.cs
- SQLMoney.cs
- ListArgumentProvider.cs
- GB18030Encoding.cs
- TypeSemantics.cs
- EventRouteFactory.cs
- BindingCompleteEventArgs.cs
- RouteData.cs
- EntitySetBase.cs
- Vector3DCollectionConverter.cs
- SafeUserTokenHandle.cs
- Authorization.cs
- DependencyProperty.cs
- ByteStack.cs
- TrustManagerPromptUI.cs
- ScopeCollection.cs
- DataGridViewRowCancelEventArgs.cs
- MsmqIntegrationInputMessage.cs
- SslStream.cs
- VersionedStream.cs
- SQLGuid.cs
- SqlGatherConsumedAliases.cs
- FontWeight.cs
- WebPartCollection.cs
- SqlEnums.cs
- FragmentNavigationEventArgs.cs
- CodeCommentStatementCollection.cs
- XpsSerializationManagerAsync.cs
- DataGridPagerStyle.cs
- ReferencedAssembly.cs
- StylusPointPropertyId.cs
- TabControlAutomationPeer.cs
- Configuration.cs
- CodeActivity.cs
- SchemaImporterExtensionsSection.cs
- SamlAdvice.cs
- NameTable.cs