/// <summary>
        ///     Determines whether the specified exception represents a transient failure that can be compensated by a retry.
        /// </summary>
        /// <param name="ex">The exception object to be verified.</param>
        /// <returns>
        ///     true if the specified exception is considered as transient; otherwise, false.
        /// </returns>
        public bool IsTransient(Exception ex)
        {
            if (ex != null)
            {
                SqlException sqlException;
                if ((sqlException = ex as SqlException) != null)
                {
                    foreach (SqlError error in sqlException.Errors)
                    {
                        switch (error.Number)
                        {
                        case 40501:
                            ThrottlingCondition throttlingCondition = ThrottlingCondition.FromError(error);
                            sqlException.Data[throttlingCondition.ThrottlingMode.GetType().Name] = ((object)throttlingCondition.ThrottlingMode).ToString();
                            sqlException.Data[throttlingCondition.GetType().Name] = throttlingCondition;
                            return(true);

                        case 40540:
                        case 40613:
                        case 10928:
                        case 10929:
                        case 40143:
                        case 40197:
                        case 233:
                        case 10053:
                        case 10054:
                        case 10060:
                        case 20:
                        case 64:
                            return(true);

                        default:
                            continue;
                        }
                    }
                }
                else
                {
                    if (ex is TimeoutException)
                    {
                        return(true);
                    }
                    EntityException entityException;
                    if ((entityException = ex as EntityException) != null)
                    {
                        return(IsTransient(entityException.InnerException));
                    }
                }
            }
            return(false);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Indicates if is a SqlException.
        /// </summary>
        /// <param name="ex">An exception.</param>
        /// <returns>True if SqlException, false otherwise.</returns>
        public bool IsTransient(Exception ex)
        {
            if (ex != null)
            {
                SqlException exception = ex as SqlException;
                if (exception != null)
                {
                    foreach (SqlError error in exception.Errors)
                    {
                        switch (error.Number)
                        {
                        case 0x2745:
                        case 0x2746:
                        case 0x274c:
                        case 0xe9:
                        case 20:
                        case 0x40:
                        case 0x2ab0:
                        case 0x2ab1:
                        case 0x9ccf:
                        case 0x9d05:
                        case 0x9e5c:
                        case 0x9ea5:
                            return(true);

                        case 0x9e35:
                        {
                            ThrottlingCondition condition = ThrottlingCondition.FromError(error);
                            exception.Data[condition.ThrottlingMode.GetType().Name] = condition.ThrottlingMode.ToString();
                            exception.Data[condition.GetType().Name] = condition;
                            return(true);
                        }
                        }
                    }
                }
                else
                {
                    if (ex is TimeoutException)
                    {
                        return(true);
                    }
                    EntityException exception2 = ex as EntityException;
                    if (exception2 != null)
                    {
                        return(this.IsTransient(exception2.InnerException));
                    }
                }
            }
            return(false);
        }
        // this is a specific error class we need to look for see http://technet.microsoft.com/en-us/library/aa937483(v=SQL.80).aspx

        #region ITransientErrorDetectionStrategy implementation

        /// <summary>
        /// Determines whether the specified exception represents a transient failure that can be compensated by a retry.
        /// </summary>
        /// <param name="ex">The exception object to be verified.</param>
        /// <returns>true if the specified exception is considered as transient; otherwise, false.</returns>
        public bool IsTransient(Exception?ex)
        {
            switch (ex)
            {
            case null:
                return(false);

            case SqlException sqlException:
            {
                // Enumerate through all errors found in the exception.
                foreach (SqlError err in sqlException.Errors)
                {
                    switch (err.Number)
                    {
                    // SQL Error Code: 40501
                    // The service is currently busy. Retry the request after 10 seconds. Code: (reason code to be decoded).
                    case ThrottlingCondition.ThrottlingErrorNumber:
                        // Decode the reason code from the error message to determine the grounds for throttling.
                        ThrottlingCondition condition = ThrottlingCondition.FromError(err);

                        // Attach the decoded values as additional attributes to the original SQL exception.
                        sqlException.Data[condition.ThrottlingMode.GetType().Name] =
                            condition.ThrottlingMode.ToString();
                        sqlException.Data[condition.GetType().Name] = condition;

                        return(true);

                    case 0:
                        if ((err.Class == 20 || err.Class == 11) && err.State == 0 && err.Server is not null && ex.InnerException is null)
                        {
                            if (string.Equals(err.Message, Resources.SQL_SevereError, StringComparison.CurrentCultureIgnoreCase))
                            {
                                return(true);
                            }
                        }
                        return(false);

                    // SQL Error Code: 4060
                    // Cannot open database "%.*ls" requested by the login. The login failed.
                    case 4060:
                    // SQL Error Code: 10928
                    // Resource ID: %d. The %s limit for the database is %d and has been reached.
                    case 10928:
                    // SQL Error Code: 10929
                    // Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d and the current usage for the database is %d.
                    // However, the server is currently too busy to support requests greater than %d for this database.
                    case 10929:
                    // SQL Error Code: 10053
                    // A transport-level error has occurred when receiving results from the server.
                    // An established connection was aborted by the software in your host machine.
                    case 10053:
                    // SQL Error Code: 10054
                    // A transport-level error has occurred when sending the request to the server.
                    // (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
                    case 10054:
                    // SQL Error Code: 10060
                    // A network-related or instance-specific error occurred while establishing a connection to SQL Server.
                    // The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server
                    // is configured to allow remote connections. (provider: TCP Provider, error: 0 - A connection attempt failed
                    // because the connected party did not properly respond after a period of time, or established connection failed
                    // because connected host has failed to respond.)"}
                    case 10060:
                    // SQL Error Code: 40197
                    // The service has encountered an error processing your request. Please try again.
                    case 40197:
                    // SQL Error Code: 40540
                    // The service has encountered an error processing your request. Please try again.
                    case 40540:
                    // SQL Error Code: 40544
                    // The database has reached its size quota. Partition or delete data, drop indexes, or consult the documentation for possible resolutions.
                    case 40544:
                    // SQL Error Code: 40549
                    // Session is terminated because you have a long-running transaction. Try shortening your transaction.
                    case 40549:
                    // SQL Error Code: 40550
                    // The session has been terminated because it has acquired too many locks. Try reading or modifying fewer rows in a single transaction.
                    case 40550:
                    // SQL Error Code: 40551
                    // The session has been terminated because of excessive TEMPDB usage. Try modifying your query to reduce the temporary table space usage.
                    case 40551:
                    // SQL Error Code: 40552
                    // The session has been terminated because of excessive transaction log space usage. Try modifying fewer rows in a single transaction.
                    case 40552:
                    // SQL Error Code: 40553
                    // The session has been terminated because of excessive memory usage. Try modifying your query to process fewer rows.
                    case 40553:
                    // SQL Error Code: 40613
                    // Database XXXX on server YYYY is not currently available. Please retry the connection later. If the problem persists, contact customer
                    // support, and provide them the session tracing ID of ZZZZZ.
                    case 40613:
                    // SQL Error Code: 40143
                    // The service has encountered an error processing your request. Please try again.
                    case 40143:
                    // SQL Error Code: 233
                    // The client was unable to establish a connection because of an error during connection initialization process before login.
                    // Possible causes include the following: the client tried to connect to an unsupported version of SQL Server; the server was too busy
                    // to accept new connections; or there was a resource limitation (insufficient memory or maximum allowed connections) on the server.
                    // (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
                    case 233:
                    // SQL Error Code: 64
                    // A connection was successfully established with the server, but then an error occurred during the login process.
                    // (provider: TCP Provider, error: 0 - The specified network name is no longer available.)
                    case 64:
                    // DBNETLIB Error Code: 20
                    // The instance of SQL Server you attempted to connect to does not support encryption.
                    case (int)ProcessNetLibErrorCode.EncryptionNotSupported:
                        return(true);
                    }
                }

                break;
            }

            case TimeoutException:
                return(true);

#if NETSTANDARD2_1 || NET5_0
            case EntityException entityException:
                return(this.IsTransient(entityException.InnerException));
#endif
            }

            return(false);
        }