异步打开连接时重试策略不起作用

本文关键字:重试 策略 不起作用 连接 异步 | 更新日期: 2023-09-27 17:51:05

在我的应用程序中,我使用企业库Topaz(瞬态故障处理应用程序块)。我试图实现SqlConnection.OpenWithRetryAsync。但这行不通。我的意思是,当我放置断点时,它只在第一次命中并抛出异常。这是我试了这么快,

    public static Task OpenWithRetryAsync(this SqlConnection connection, RetryPolicy retryPolicy)
    {
        return retryPolicy.ExecuteAsync(() =>
        {
            return connection.OpenAsync();
        });
    }

异步打开连接时重试策略不起作用

只是挖掘源代码,发现我得到一个SQL错误,这不是暂时的。我的错误代码是10065,错误是,

在建立到SQL Server的连接时发生了与网络相关或特定于实例的错误。未找到服务器或无法访问服务器。验证实例名是否正确,SQL Server是否配置为允许远程连接。(provider: TCP provider, error: 0 -试图对一个不可达的主机进行套接字操作)

当我跑的时候,

    public static Task OpenWithRetryAsync(this SqlConnection connection, RetryPolicy retryPolicy)
    {
        return retryPolicy.ExecuteAsync(async () =>
        {
            try
            {
                await connection.OpenAsync();
            }
            catch(SqlException ex)
            {
                throw CreateSqlException(10060);// got it form http://blog.gauffin.org/2014/08/how-to-create-a-sqlexception/
            }
        });
    }

那么我的重试策略就像一个魅力。

    public bool IsTransient(Exception ex)
    {
        if (ex != null)
        {
            SqlException sqlException;
            if ((sqlException = ex as SqlException) != null)
            {
                // 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.
                            var 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 != null && ex.InnerException == 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: 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;
                    }
                }
            }
            else if (ex is TimeoutException)
            {
                return true;
            }
            else
            {
                EntityException entityException;
                if ((entityException = ex as EntityException) != null)
                {
                    return this.IsTransient(entityException.InnerException);
                }
            }
        }
        return false;
    }

ADO。. NET SqlConnection类附带一个OpenWithRetry方法

例如:

connection.OpenWithRetry(retryPolicy);

看看这个网站,我发现它非常有用,当我正在寻找一个重试策略的地方

http://geekswithblogs.net/ScottKlein/archive/2012/01/27/understanding-sql-azure-throttling-and-implementing-retry-logic.aspx