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 IDictionary transactionConnectionTable;
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 IDictionary transactionConnectionTable;
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
- GridViewUpdateEventArgs.cs
- RequestQueryParser.cs
- DefaultValueAttribute.cs
- ManagedWndProcTracker.cs
- SimplePropertyEntry.cs
- HashCodeCombiner.cs
- ColumnMapCopier.cs
- GridViewAutomationPeer.cs
- RootBuilder.cs
- SystemWebSectionGroup.cs
- ChineseLunisolarCalendar.cs
- DbConnectionInternal.cs
- AuthenticatedStream.cs
- DataGridCell.cs
- GeneratedContractType.cs
- WebPartConnectionsDisconnectVerb.cs
- FormViewInsertEventArgs.cs
- QilValidationVisitor.cs
- exports.cs
- TextElementEnumerator.cs
- DependencyObject.cs
- Point3DKeyFrameCollection.cs
- SignedPkcs7.cs
- TPLETWProvider.cs
- ProvidePropertyAttribute.cs
- GeneralTransform3DGroup.cs
- FastPropertyAccessor.cs
- KeyValuePair.cs
- ParameterSubsegment.cs
- DocumentScope.cs
- ElementUtil.cs
- DbConnectionPoolCounters.cs
- SspiSafeHandles.cs
- SingleAnimationBase.cs
- SrgsElementFactory.cs
- translator.cs
- AtomMaterializer.cs
- DbCommandTree.cs
- SinglePageViewer.cs
- Point3D.cs
- RectangleGeometry.cs
- InkCanvasSelection.cs
- StringWriter.cs
- NavigatingCancelEventArgs.cs
- QilList.cs
- OleTxTransaction.cs
- ClockController.cs
- CacheOutputQuery.cs
- KeyedPriorityQueue.cs
- FixUp.cs
- WinEventTracker.cs
- SQLDecimal.cs
- CommentEmitter.cs
- keycontainerpermission.cs
- ImageSource.cs
- Matrix3D.cs
- ChtmlTextWriter.cs
- StandardCommands.cs
- TabRenderer.cs
- CaseStatement.cs
- AsyncSerializedWorker.cs
- SignedInfo.cs
- FontUnitConverter.cs
- precedingquery.cs
- DataGridViewLinkCell.cs
- UnsafeMethods.cs
- OutputScopeManager.cs
- Image.cs
- LineBreak.cs
- SystemIPInterfaceProperties.cs
- hebrewshape.cs
- Peer.cs
- AnnotationHighlightLayer.cs
- Parameter.cs
- TcpClientCredentialType.cs
- IncrementalCompileAnalyzer.cs
- DbgCompiler.cs
- Focus.cs
- ChangesetResponse.cs
- WebPartExportVerb.cs
- ResourcePermissionBaseEntry.cs
- WindowsTokenRoleProvider.cs
- CreateUserWizardStep.cs
- ClientType.cs
- XpsS0ValidatingLoader.cs
- CustomErrorCollection.cs
- XmlProcessingInstruction.cs
- cache.cs
- CheckedListBox.cs
- RelationalExpressions.cs
- TreeNodeBindingCollection.cs
- TimeoutException.cs
- CodeStatementCollection.cs
- ControlBuilder.cs
- SplineKeyFrames.cs
- DNS.cs
- serverconfig.cs
- ProcessModule.cs
- ComponentSerializationService.cs
- HtmlShim.cs