internal PersistenceDBAccessor(DbResourceAllocator dbResourceAllocator, Transaction transaction, WorkflowCommitWorkBatchService transactionService)
 {
     this.dbResourceAllocator = dbResourceAllocator;
     this.localTransaction = DbResourceAllocator.GetLocalTransaction(transactionService, transaction);
     this.connection = this.dbResourceAllocator.GetEnlistedConnection(transactionService, transaction, out this.needToCloseConnection);
     this.dbRetry = new DbRetry(false);
 }
 internal void DetectSharedConnectionConflict(WorkflowCommitWorkBatchService transactionService)
 {
     SharedConnectionWorkflowCommitWorkBatchService service = transactionService as SharedConnectionWorkflowCommitWorkBatchService;
     if ((service != null) && (string.Compare(service.ConnectionString, this.connString, StringComparison.Ordinal) != 0))
     {
         throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.SharedConnectionStringSpecificationConflict, new object[] { this.connString, service.ConnectionString }));
     }
 }
        internal void DetectSharedConnectionConflict(WorkflowCommitWorkBatchService transactionService)
        {
            SharedConnectionWorkflowCommitWorkBatchService service = transactionService as SharedConnectionWorkflowCommitWorkBatchService;

            if ((service != null) && (string.Compare(service.ConnectionString, this.connString, StringComparison.Ordinal) != 0))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.SharedConnectionStringSpecificationConflict, new object[] { this.connString, service.ConnectionString }));
            }
        }
        internal static DbTransaction GetLocalTransaction(WorkflowCommitWorkBatchService txSvc, Transaction transaction)
        {
            DbTransaction        dBTransaction  = null;
            SharedConnectionInfo connectionInfo = GetConnectionInfo(txSvc, transaction);

            if (connectionInfo != null)
            {
                dBTransaction = connectionInfo.DBTransaction;
            }
            return(dBTransaction);
        }
 private static SharedConnectionInfo GetConnectionInfo(WorkflowCommitWorkBatchService txSvc, Transaction transaction)
 {
     SharedConnectionInfo connectionInfo = null;
     SharedConnectionWorkflowCommitWorkBatchService service = txSvc as SharedConnectionWorkflowCommitWorkBatchService;
     if (service != null)
     {
         connectionInfo = service.GetConnectionInfo(transaction);
         if (connectionInfo == null)
         {
             throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InvalidTransaction, new object[0]));
         }
     }
     return connectionInfo;
 }
        private static SharedConnectionInfo GetConnectionInfo(WorkflowCommitWorkBatchService txSvc, Transaction transaction)
        {
            SharedConnectionInfo connectionInfo = null;
            SharedConnectionWorkflowCommitWorkBatchService service = txSvc as SharedConnectionWorkflowCommitWorkBatchService;

            if (service != null)
            {
                connectionInfo = service.GetConnectionInfo(transaction);
                if (connectionInfo == null)
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InvalidTransaction, new object[0]));
                }
            }
            return(connectionInfo);
        }
 internal DbConnection GetEnlistedConnection(WorkflowCommitWorkBatchService txSvc, Transaction transaction, out bool isNewConnection)
 {
     DbConnection dBConnection;
     SharedConnectionInfo connectionInfo = GetConnectionInfo(txSvc, transaction);
     if (connectionInfo != null)
     {
         dBConnection = connectionInfo.DBConnection;
         isNewConnection = false;
         return dBConnection;
     }
     dBConnection = this.OpenNewConnection();
     dBConnection.EnlistTransaction(transaction);
     isNewConnection = true;
     return dBConnection;
 }
 /// <summary>
 /// DB access done under a transaction and uses a connection enlisted to this transaction.
 /// </summary>
 /// <param name="dbResourceAllocator">Helper to get database connection/command/store procedure parameters/etc</param>
 /// <param name="transaction">The transaction to do this work under</param>        
 internal PersistenceDBAccessor(
     DbResourceAllocator dbResourceAllocator,
     System.Transactions.Transaction transaction,
     WorkflowCommitWorkBatchService transactionService)
 {
     this.dbResourceAllocator = dbResourceAllocator;
     this.localTransaction = DbResourceAllocator.GetLocalTransaction(
         transactionService, transaction);
     // Get a connection enlisted to this transaction, may or may not need to be freed depending on 
     // if the transaction does connection sharing
     this.connection = this.dbResourceAllocator.GetEnlistedConnection(
         transactionService, transaction, out needToCloseConnection);
     //
     // No retries for external transactions
     this.dbRetry = new DbRetry(false);
 }
        internal DbConnection GetEnlistedConnection(WorkflowCommitWorkBatchService txSvc, Transaction transaction, out bool isNewConnection)
        {
            DbConnection         dBConnection;
            SharedConnectionInfo connectionInfo = GetConnectionInfo(txSvc, transaction);

            if (connectionInfo != null)
            {
                dBConnection    = connectionInfo.DBConnection;
                isNewConnection = false;
                return(dBConnection);
            }
            dBConnection = this.OpenNewConnection();
            dBConnection.EnlistTransaction(transaction);
            isNewConnection = true;
            return(dBConnection);
        }
        /*
         * private void SetLocalProvider(string connectionString)
         * {
         *  // Assume caller already validated the connection string
         *  MatchCollection providers = Regex.Matches(connectionString, @"(^|;)\s*provider\s*=[^;$]*(;|$)", RegexOptions.IgnoreCase);
         *
         *  // Cannot use DbConnectionStringBuilder because it selects the last provider, not the first one, by itself.
         *  // A legal Sql connection string allows for multiple provider specification and
         *  // selects the first provider
         *  if (providers.Count > 0)
         *  {
         *      // Check if the first one matches "sqloledb" or "sqloledb.<digit>"
         *      if (Regex.IsMatch(providers[0].Value, @"provider\s*=\s*sqloledb(\.\d+)?\s*(;|$)", RegexOptions.IgnoreCase))
         *      {
         *          this.localProvider = Provider.OleDB;
         *      }
         *      else
         *      {
         *          // We don't support other providers
         *          throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,ExecutionStringManager.UnsupportedSqlProvider, providers[0].Value));
         *      }
         *  }
         *  else
         *  {
         *      // SqlClient provider requires no provider keyword specified in connection string
         *      this.localProvider = Provider.SqlClient;
         *  }
         * }
         */

        private static SharedConnectionInfo GetConnectionInfo(WorkflowCommitWorkBatchService txSvc, Transaction transaction)
        {
            SharedConnectionInfo connectionInfo = null;

            SharedConnectionWorkflowCommitWorkBatchService scTxSvc = txSvc as SharedConnectionWorkflowCommitWorkBatchService;

            if (scTxSvc != null)
            {
                connectionInfo = scTxSvc.GetConnectionInfo(transaction);

                // The transaction service can't find entry if the transaction has been completed.
                // be sure to propate the error so durable services can cast to appropriate exception
                if (connectionInfo == null)
                {
                    throw new ArgumentException(
                              String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InvalidTransaction));
                }
            }
            return(connectionInfo);
        }
 protected internal override void Start()
 {
     WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SqlWorkflowPersistenceService({1}): Starting, LoadInternalSeconds={0}", new object[] { this.loadingInterval.TotalSeconds, this._serviceInstanceId.ToString() });
     this._dbResourceAllocator = new DbResourceAllocator(base.Runtime, this.configParameters, this.unvalidatedConnectionString);
     this._transactionService  = base.Runtime.GetService <WorkflowCommitWorkBatchService>();
     this._dbResourceAllocator.DetectSharedConnectionConflict(this._transactionService);
     if (!this._ignoreCommonEnableRetries && (base.Runtime != null))
     {
         NameValueConfigurationCollection commonParameters = base.Runtime.CommonParameters;
         if (commonParameters != null)
         {
             foreach (string str in commonParameters.AllKeys)
             {
                 if (string.Compare("EnableRetries", str, StringComparison.OrdinalIgnoreCase) == 0)
                 {
                     this._enableRetries = bool.Parse(commonParameters[str].Value);
                     break;
                 }
             }
         }
     }
     base.Start();
 }
 protected internal override void CommitWorkBatch(WorkflowCommitWorkBatchService.CommitWorkBatchCallback commitWorkBatchCallback)
 {
     DbRetry retry = new DbRetry(this._enableRetries);
     short retryCount = 0;
 Label_000E:
     if (null != Transaction.Current)
     {
         retryCount = retry.MaxRetries;
     }
     try
     {
         base.CommitWorkBatch(commitWorkBatchCallback);
     }
     catch (Exception exception)
     {
         WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "DefaultWorkflowCommitWorkBatchService caught exception from commitWorkBatchCallback: " + exception.ToString());
         if (!retry.TryDoRetry(ref retryCount))
         {
             throw;
         }
         WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "DefaultWorkflowCommitWorkBatchService retrying commitWorkBatchCallback (retry attempt " + retryCount.ToString(CultureInfo.InvariantCulture) + ")");
         goto Label_000E;
     }
 }
        /// <summary>
        /// Gets a connection enlisted to the transaction.
        /// If the transaction already has a connection attached to it, we return that,
        /// otherwise we create a new connection and enlist to the transaction
        /// </summary>
        /// <param name="transaction"></param>
        /// <param name="isNewConnection">output if we created a connection</param>
        /// <returns></returns>
        internal DbConnection GetEnlistedConnection(WorkflowCommitWorkBatchService txSvc, Transaction transaction, out bool isNewConnection)
        {
            DbConnection         connection;
            SharedConnectionInfo connectionInfo = GetConnectionInfo(txSvc, transaction);

            if (connectionInfo != null)
            {
                connection = connectionInfo.DBConnection;
                Debug.Assert((connection != null), "null connection");
                Debug.Assert((connection.State == System.Data.ConnectionState.Open),
                             "Invalid connection state " + connection.State + " for connection " + connection);

                isNewConnection = false;
            }
            else
            {
                connection = this.OpenNewConnection();
                connection.EnlistTransaction(transaction);

                isNewConnection = true;
            }

            return(connection);
        }
        /*
        private void SetLocalProvider(string connectionString)
        {
            // Assume caller already validated the connection string
            MatchCollection providers = Regex.Matches(connectionString, @"(^|;)\s*provider\s*=[^;$]*(;|$)", RegexOptions.IgnoreCase);

            // Cannot use DbConnectionStringBuilder because it selects the last provider, not the first one, by itself.
            // A legal Sql connection string allows for multiple provider specification and 
            // selects the first provider
            if (providers.Count > 0)
            {
                // Check if the first one matches "sqloledb" or "sqloledb.<digit>"
                if (Regex.IsMatch(providers[0].Value, @"provider\s*=\s*sqloledb(\.\d+)?\s*(;|$)", RegexOptions.IgnoreCase))
                {
                    this.localProvider = Provider.OleDB;
                }
                else
                {
                    // We don't support other providers
                    throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,ExecutionStringManager.UnsupportedSqlProvider, providers[0].Value));
                }
            }
            else
            {
                // SqlClient provider requires no provider keyword specified in connection string
                this.localProvider = Provider.SqlClient;
            }
        }
        */

        private static SharedConnectionInfo GetConnectionInfo(WorkflowCommitWorkBatchService txSvc, Transaction transaction)
        {
            SharedConnectionInfo connectionInfo = null;

            SharedConnectionWorkflowCommitWorkBatchService scTxSvc = txSvc as SharedConnectionWorkflowCommitWorkBatchService;
            if (scTxSvc != null)
            {
                connectionInfo = scTxSvc.GetConnectionInfo(transaction);

                // The transaction service can't find entry if the transaction has been completed.
                // be sure to propate the error so durable services can cast to appropriate exception
                if (connectionInfo == null)
                    throw new ArgumentException(
                        String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InvalidTransaction));
            }
            return connectionInfo;
        }
        internal static DbTransaction GetLocalTransaction(WorkflowCommitWorkBatchService txSvc, Transaction transaction)
        {
            DbTransaction localTransaction = null;
            SharedConnectionInfo connectionInfo = GetConnectionInfo(txSvc, transaction);

            if (connectionInfo != null)
                localTransaction = connectionInfo.DBTransaction;

            return localTransaction;
        }
        /// <summary>
        /// Gets a connection enlisted to the transaction.  
        /// If the transaction already has a connection attached to it, we return that,
        /// otherwise we create a new connection and enlist to the transaction
        /// </summary>
        /// <param name="transaction"></param>
        /// <param name="isNewConnection">output if we created a connection</param>
        /// <returns></returns>
        internal DbConnection GetEnlistedConnection(WorkflowCommitWorkBatchService txSvc, Transaction transaction, out bool isNewConnection)
        {
            DbConnection connection;
            SharedConnectionInfo connectionInfo = GetConnectionInfo(txSvc, transaction);

            if (connectionInfo != null)
            {
                connection = connectionInfo.DBConnection;
                Debug.Assert((connection != null), "null connection");
                Debug.Assert((connection.State == System.Data.ConnectionState.Open),
                    "Invalid connection state " + connection.State + " for connection " + connection);

                isNewConnection = false;
            }
            else
            {
                connection = this.OpenNewConnection();
                connection.EnlistTransaction(transaction);

                isNewConnection = true;
            }

            return connection;
        }
        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();
                    }
                }
            }
        }
 internal PersistenceDBAccessor(DbResourceAllocator dbResourceAllocator, Transaction transaction, WorkflowCommitWorkBatchService transactionService)
 {
     this.dbResourceAllocator = dbResourceAllocator;
     this.localTransaction    = DbResourceAllocator.GetLocalTransaction(transactionService, transaction);
     this.connection          = this.dbResourceAllocator.GetEnlistedConnection(transactionService, transaction, out this.needToCloseConnection);
     this.dbRetry             = new DbRetry(false);
 }
 protected internal override void Start()
 {
     WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SqlWorkflowPersistenceService({1}): Starting, LoadInternalSeconds={0}", new object[] { this.loadingInterval.TotalSeconds, this._serviceInstanceId.ToString() });
     this._dbResourceAllocator = new DbResourceAllocator(base.Runtime, this.configParameters, this.unvalidatedConnectionString);
     this._transactionService = base.Runtime.GetService<WorkflowCommitWorkBatchService>();
     this._dbResourceAllocator.DetectSharedConnectionConflict(this._transactionService);
     if (!this._ignoreCommonEnableRetries && (base.Runtime != null))
     {
         NameValueConfigurationCollection commonParameters = base.Runtime.CommonParameters;
         if (commonParameters != null)
         {
             foreach (string str in commonParameters.AllKeys)
             {
                 if (string.Compare("EnableRetries", str, StringComparison.OrdinalIgnoreCase) == 0)
                 {
                     this._enableRetries = bool.Parse(commonParameters[str].Value);
                     break;
                 }
             }
         }
     }
     base.Start();
 }
        override protected internal void Start()
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SqlWorkflowPersistenceService({1}): Starting, LoadInternalSeconds={0}", loadingInterval.TotalSeconds, _serviceInstanceId.ToString());

            _dbResourceAllocator = new DbResourceAllocator(this.Runtime, this.configParameters, this.unvalidatedConnectionString);

            // Check connection string mismatch if using SharedConnectionWorkflowTransactionService
            _transactionService = Runtime.GetService<WorkflowCommitWorkBatchService>();
            _dbResourceAllocator.DetectSharedConnectionConflict(_transactionService);

            //
            // 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(EnableRetriesToken, key, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            _enableRetries = bool.Parse(commonConfigurationParameters[key].Value);
                            break;
                        }
                    }
                }
            }

            base.Start();
        }
 protected internal override void CommitWorkBatch(WorkflowCommitWorkBatchService.CommitWorkBatchCallback commitWorkBatchCallback)
 {
     ManualResetEvent event2;
     DbRetry retry = new DbRetry(this._enableRetries);
     short maxRetries = retry.MaxRetries;
 Label_0013:
     event2 = new ManualResetEvent(false);
     Transaction transaction = null;
     SharedConnectionInfo connectionInfo = null;
     try
     {
         if (null == Transaction.Current)
         {
             maxRetries = 0;
             transaction = new CommittableTransaction();
             connectionInfo = new SharedConnectionInfo(this.dbResourceAllocator, transaction, false, event2);
         }
         else
         {
             transaction = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
             connectionInfo = new SharedConnectionInfo(this.dbResourceAllocator, transaction, true, event2);
         }
         this.AddToConnectionInfoTable(transaction, connectionInfo);
         using (TransactionScope scope = new TransactionScope(transaction))
         {
             try
             {
                 commitWorkBatchCallback();
                 scope.Complete();
             }
             finally
             {
                 this.RemoveConnectionFromInfoTable(transaction);
                 event2.Set();
             }
         }
         CommittableTransaction transaction2 = transaction as CommittableTransaction;
         if (transaction2 != null)
         {
             transaction2.Commit();
         }
         DependentTransaction transaction3 = transaction as DependentTransaction;
         if (transaction3 != null)
         {
             transaction3.Complete();
         }
     }
     catch (Exception exception)
     {
         transaction.Rollback();
         WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "SharedConnectionWorkflowCommitWorkBatchService caught exception from commitWorkBatchCallback: " + exception.ToString());
         if (!retry.TryDoRetry(ref maxRetries))
         {
             throw;
         }
         WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SharedConnectionWorkflowCommitWorkBatchService retrying commitWorkBatchCallback (retry attempt " + maxRetries.ToString(CultureInfo.InvariantCulture) + ")");
         goto Label_0013;
     }
     finally
     {
         event2.Close();
         if (transaction != null)
         {
             transaction.Dispose();
         }
     }
 }