/// <summary>
 /// Initializes a new instance of the <see cref="TransactionRetryScope"/> class with the specified retry policy.
 /// </summary>
 /// <param name="retryPolicy">The retry policy that determines whether to retry the execution of the entire scope if a transient fault is encountered.</param>
 /// <param name="unitOfWork">A delegate that represents the executable unit of work that will be retried upon failure.</param>
 public TransactionRetryScope(RetryPolicy retryPolicy, Action unitOfWork)
     : this(TransactionScopeOption.Required, retryPolicy, unitOfWork)
 {
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="TransactionRetryScope"/> class with the specified time-out value, transaction scope options, and retry policy.
        /// Uses the ReadCommitted isolation level by default.
        /// </summary>
        /// <param name="scopeOption">One of the enumeration values that specifies the transaction requirements associated with this transaction scope.</param>
        /// <param name="scopeTimeout">The TimeSpan after which the transaction scope times out and aborts the transaction.</param>
        /// <param name="retryPolicy">The retry policy that determines whether to retry the execution of the entire scope if a transient fault is encountered.</param>
        /// <param name="unitOfWork">A delegate that represents the executable unit of work that will be retried upon failure.</param>
        public TransactionRetryScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout, RetryPolicy retryPolicy, Action unitOfWork)
        {
            this.transactionScopeInit = () =>
            {
                var txOptions = new TransactionOptions {
                    IsolationLevel = IsolationLevel.ReadCommitted, Timeout = scopeTimeout
                };

                return(new TransactionScope(scopeOption, txOptions));
            };

            this.transactionScope = this.transactionScopeInit();
            this.retryPolicy      = retryPolicy;
            this.unitOfWork       = unitOfWork;

            // Set up the callback method for the specified retry policy.
            this.InitializeRetryPolicy();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TransactionRetryScope"/> class with the specified requirements and retry policy.
        /// </summary>
        /// <param name="scopeOption">One of the enumeration values that specifies the transaction requirements associated with this transaction scope.</param>
        /// <param name="transactionOptions">A <see cref="System.Transactions.TransactionOptions"/> structure that describes the transaction options to use if a new transaction is created. If an existing transaction is used, the time-out value in this parameter applies to the transaction scope. If that time expires before the scope is disposed, the transaction is aborted.</param>
        /// <param name="retryPolicy">The retry policy that determines whether to retry the execution of the entire scope if a transient fault is encountered.</param>
        /// <param name="unitOfWork">A delegate that represents the executable unit of work that will be retried upon failure.</param>
        public TransactionRetryScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions, RetryPolicy retryPolicy, Action unitOfWork)
        {
            this.transactionScopeInit = () => new TransactionScope(scopeOption, transactionOptions);

            this.transactionScope = this.transactionScopeInit();
            this.retryPolicy      = retryPolicy;
            this.unitOfWork       = unitOfWork;

            // Set up the callback method for the specified retry policy.
            this.InitializeRetryPolicy();
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="TransactionRetryScope"/> class with the specified requirements and retry policy.
 /// Uses the ReadCommitted isolation level by default.
 /// </summary>
 /// <param name="scopeOption">One of the enumeration values that specifies the transaction requirements associated with this transaction scope.</param>
 /// <param name="retryPolicy">The retry policy that determines whether to retry the execution of the entire scope if a transient fault is encountered.</param>
 /// <param name="unitOfWork">A delegate that represents the executable unit of work that will be retried upon failure.</param>
 public TransactionRetryScope(TransactionScopeOption scopeOption, RetryPolicy retryPolicy, Action unitOfWork)
     : this(scopeOption, TimeSpan.Zero, retryPolicy, unitOfWork)
 {
 }
예제 #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ReliableSqlConnection"/> class with the specified connection string
        /// and a policy that defines whether to retry a request if a connection or command
        /// fails.
        /// </summary>
        /// <param name="connectionString">The connection string used to open the SQL Database.</param>
        /// <param name="connectionRetryPolicy">The retry policy that defines whether to retry a request if a connection fails to be established.</param>
        /// <param name="commandRetryPolicy">The retry policy that defines whether to retry a request if a command fails to be executed.</param>
        public ReliableSqlConnection(string connectionString, RetryPolicy connectionRetryPolicy, RetryPolicy commandRetryPolicy)
        {
            this.connectionString      = connectionString;
            this.underlyingConnection  = new SqlConnection(connectionString);
            this.connectionRetryPolicy = connectionRetryPolicy;
            this.commandRetryPolicy    = commandRetryPolicy;

            // Configure a special retry policy that enables detecting network connectivity errors to be able to determine whether we need to failover
            // to the original connection string containing the DNS name of the SQL Database server.
            this.connectionStringFailoverPolicy = new RetryPolicy <NetworkConnectivityErrorDetectionStrategy>(1, TimeSpan.FromMilliseconds(1));
        }
예제 #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ReliableSqlConnection"/> class with the specified connection string
 /// and a policy that defines whether to retry a request if a connection or command
 /// fails.
 /// </summary>
 /// <param name="connectionString">The connection string used to open the SQL Database.</param>
 /// <param name="retryPolicy">The retry policy that defines whether to retry a request if a connection or command fails.</param>
 public ReliableSqlConnection(string connectionString, RetryPolicy retryPolicy)
     : this(connectionString, retryPolicy, RetryManager.Instance.GetDefaultSqlCommandRetryPolicy() ?? retryPolicy)
 {
 }
예제 #7
0
        /// <summary>
        /// Executes a SQL command and returns the number of rows affected.
        /// </summary>
        /// <param name="command">The SQL command to be executed.</param>
        /// <param name="retryPolicy">The retry policy that defines whether to retry a command if a connection fails while executing the command.</param>
        /// <returns>The number of rows affected.</returns>
        public int ExecuteCommand(IDbCommand command, RetryPolicy retryPolicy)
        {
            var result = this.ExecuteCommand <NonQueryResult>(command, retryPolicy);

            return(result.RecordsAffected);
        }
예제 #8
0
        public T ExecuteCommand <T>(IDbCommand command, RetryPolicy retryPolicy, CommandBehavior behavior)
        {
            var actionResult = default(T);

            var resultType = typeof(T);

            var hasOpenedConnection = false;

            var closeOpenedConnectionOnSuccess = false;

            try
            {
                (retryPolicy ?? RetryPolicy.NoRetry).ExecuteAction(() =>
                {
                    actionResult = this.connectionStringFailoverPolicy.ExecuteAction(() =>
                    {
                        // Make sure the command has been associated with a valid connection. If not, associate it with an opened SQL connection.
                        if (command.Connection == null)
                        {
                            // Open a new connection and assign it to the command object.
                            command.Connection  = this.Open();
                            hasOpenedConnection = true;
                        }

                        // Verify whether or not the connection is valid and is open. This code may be retried therefore
                        // it is important to ensure that a connection is re-established should it have previously failed.
                        if (command.Connection.State != ConnectionState.Open)
                        {
                            command.Connection.Open();
                            hasOpenedConnection = true;
                        }

                        if (typeof(IDataReader).IsAssignableFrom(resultType))
                        {
                            closeOpenedConnectionOnSuccess = false;

                            return((T)command.ExecuteReader(behavior));
                        }

                        if (resultType == typeof(XmlReader))
                        {
                            if (command is SqlCommand)
                            {
                                object result;
                                var xmlReader = (command as SqlCommand).ExecuteXmlReader();

                                closeOpenedConnectionOnSuccess = false;

                                if ((behavior & CommandBehavior.CloseConnection) == CommandBehavior.CloseConnection)
                                {
                                    // Implicit conversion from XmlReader to <T> via an intermediary object.
                                    result = new SqlXmlReader(command.Connection, xmlReader);
                                }
                                else
                                {
                                    // Implicit conversion from XmlReader to <T> via an intermediary object.
                                    result = xmlReader;
                                }

                                return((T)result);
                            }

                            throw new NotSupportedException();
                        }

                        if (resultType == typeof(NonQueryResult))
                        {
                            var result = new NonQueryResult {
                                RecordsAffected = command.ExecuteNonQuery()
                            };

                            closeOpenedConnectionOnSuccess = true;

                            return((T)Convert.ChangeType(result, resultType, CultureInfo.InvariantCulture));
                        }
                        else
                        {
                            var result = command.ExecuteScalar();

                            closeOpenedConnectionOnSuccess = true;

                            if (result != null)
                            {
                                return((T)Convert.ChangeType(result, resultType, CultureInfo.InvariantCulture));
                            }

                            return(default(T));
                        }
                    });
                });

                if (hasOpenedConnection && closeOpenedConnectionOnSuccess &&
                    command.Connection != null && command.Connection.State == ConnectionState.Open)
                {
                    command.Connection.Close();
                }
            }
            catch (Exception)
            {
                if (hasOpenedConnection &&
                    command.Connection != null && command.Connection.State == ConnectionState.Open)
                {
                    command.Connection.Close();
                }

                throw;
            }

            return(actionResult);
        }
예제 #9
0
 /// <summary>
 /// Executes a SQL command by using the specified retry policy, and returns a result that is defined by the specified type <typeparamref name="T"/>
 /// </summary>
 /// <typeparam name="T">IDataReader, XmlReader, or any other .NET Framework type that defines the type of result to be returned.</typeparam>
 /// <param name="command">The SQL command to be executed.</param>
 /// <param name="retryPolicy">The retry policy that defines whether to retry a command if a connection fails while executing the command.</param>
 /// <returns>An instance of an IDataReader, XmlReader, or any other .NET Frameork object that contains the result.</returns>
 public T ExecuteCommand <T>(IDbCommand command, RetryPolicy retryPolicy)
 {
     return(this.ExecuteCommand <T>(command, retryPolicy, CommandBehavior.Default));
 }