//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ #region Using directives using System; using System.Diagnostics; using System.Transactions; using System.Data.Common; using System.Threading; #endregion namespace System.Workflow.Runtime.Hosting { /// /// This class keeps the following associated with a Transaction /// - a connection that participates in the transaction. /// - an optional local transaction (DbTransaction) generated from the single-phase-committed Transaction. /// The connection and the local transaction are passed around to different host components to /// do transacted DB work using the shared connection. /// internal sealed class SharedConnectionInfo : IDisposable { readonly DbConnection connection; readonly DbTransaction localTransaction; private bool disposed; private ManualResetEvent handle; #region Constructor /// /// Instantiate an opened connection enlisted to the Transaction /// if promotable is false, the Transaction wraps a local /// transaction inside and can never be promoted /// /// /// /// internal SharedConnectionInfo( DbResourceAllocator dbResourceAllocator, Transaction transaction, bool wantPromotable, ManualResetEvent handle) { Debug.Assert((transaction != null), "Null Transaction!"); if (null == handle) throw new ArgumentNullException("handle"); this.handle = handle; if (wantPromotable) { // Enlist a newly opened connection to this regular Transaction this.connection = dbResourceAllocator.OpenNewConnection(); this.connection.EnlistTransaction(transaction); } else { // Make this transaction no longer promotable by attaching our // IPromotableSinglePhaseNotification implementation (LocalTranscaction) // and track the DbConnection and DbTransaction associated with the LocalTranscaction LocalTransaction localTransaction = new LocalTransaction(dbResourceAllocator, handle); transaction.EnlistPromotableSinglePhase(localTransaction); this.connection = localTransaction.Connection; this.localTransaction = localTransaction.Transaction; } } #endregion Constructor #region Accessors internal DbConnection DBConnection { get { return this.connection; } } internal DbTransaction DBTransaction { get { return this.localTransaction; } } #endregion Accessors #region IDisposable Members public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!this.disposed) { // // If we're using a LocalTransaction it will close the connection // in it's IPromotableSinglePhaseNotification methods if ((this.localTransaction == null) && (null != connection)) this.connection.Dispose(); } this.disposed = true; } #endregion } }