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

时间:2015-05-28 09:37:43

标签: c# async-await enterprise-library

在我的应用程序中,我正在使用Enterprise Library Topaz(瞬态故障处理应用程序块)。我正在尝试实现SqlConnection.OpenWithRetryAsync。但它不起作用。我的意思是当我把我的断点放在第一次并且抛出异常时。这是我试过的那么快,

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

2 个答案:

答案 0 :(得分:0)

只是深入挖掘源代码,发现我得到的SQL错误并非短暂的。我的错误代码是10065,错误是,

  

建立与SQL Server的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称是否正确,以及SQL Server是否配置为允许远程连接。 (提供程序:TCP提供程序,错误: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;
    }

答案 1 :(得分:0)

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

例如:

connection.OpenWithRetry(retryPolicy);

看看这个网站,我发现当我考虑获得重试政策时它非常有用

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