处理数据库连接问题的正确方法

ILo*_*low 13 c# ado.net sqlconnection azure-sql-database

我在尝试连接数据库时遇到以下错误:

建立与SQL Server的连接时发生与网络相关或特定于实例的错误.服务器未找到或无法访问.验证实例名称是否正确,以及SQL Server是否配置为允许远程连接.(提供者:命名管道提供程序,错误:40 - 无法打开与SQL Server的连接)

现在有时我得到这个错误,有时我不这样做,例如:当我第一次运行我的程序时,它成功打开连接,当我第二次运行时,我得到这个错误,下次我再次运行我的程序然后我不会得到错误.

当我尝试通过SSMS连接到同一个数据库服务器,然后我能够成功连接,但我只在我的程序中遇到此网络问题.

数据库不在我的LOCAL中.它在AZURE上.

我的本地数据库没有出现此错误.

代码:

public class AddOperation
{
    public void Start()
    {
          using (var processor = new MyProcessor())
          {
              for (int i = 0; i < 2; i++)
              {
                  if(i==0)
                  {
                     var connection = new SqlConnection("Connection string 1");
                     processor.Process(connection);
                  }
                  else
                  {
                      var connection = new SqlConnection("Connection string 2");
                      processor.Process(connection);
                  }   
              }
          }
    }       
}

public class MyProcessor : IDisposable
{
    public void Process(DbConnection cn)
        {
            using (var cmd = cn.CreateCommand())
            {
                cmd.CommandText = "query";
                cmd.CommandTimeout = 1800;
                cn.Open();//Sometimes work sometimes dont
                using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                { 
                   //code
                }
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

所以我对两件事感到困惑:

1)ConnectionTimeout:我是否应该增加connectiontimeout并解决我的异常连接问题?

2)重试尝试策略:我应该实现如下的重试连接机制:

public static void OpenConnection(DbConnection cn, int maxAttempts = 1)
        {
            int attempts = 0;
            while (true)
            {
                try
                {
                    cn.Open();
                    return;
                }
                catch
                {
                    attempts++;
                    if (attempts >= maxAttempts) throw;
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

我对上面的2个选项感到困惑.

任何人都可以建议我处理这个问题的更好方法是什么?

Eri*_*kEJ 6

使用新版本的 .NET(4.6.1 或更高版本),然后利用内置的弹性功能:

ConnectRetryCount、ConnectRetryInterval 和连接超时。

查看更多信息:https : //docs.microsoft.com/en-us/azure/sql-database/sql-database-connectivity-issues#net-sqlconnection-parameters-for-connection-retry


Alb*_*llo 5

正如您可以在此处阅读的那样,即使对于安装在Azure VM(IaaS)上的SQL Server,也建议使用重试逻辑.

故障处理:您的应用程序代码包括重试逻辑和瞬态故障处理?在代码中包括适当的重试逻辑和瞬态故障处理补救应该是一种通用的最佳实践,包括本地和云,IaaS或PaaS.如果缺少此特性,Azure VM中的Azure SQLDB和SQL Server上的应用程序问题可能会增加,但在这种情况下,建议使用后者.

建议使用增量重试逻辑.

从应用程序所需的应用程序块中实例化对象有两种基本方法.在第一种方法中,您可以显式实例化代码中的所有对象,如以下代码段所示:

var retryStrategy = new Incremental(5, TimeSpan.FromSeconds(1), 
  TimeSpan.FromSeconds(2));

var retryPolicy =
  new RetryPolicy<SqlDatabaseTransientErrorDetectionStrategy>(retryStrategy);
Run Code Online (Sandbox Code Playgroud)

在第二种方法中,您可以从配置数据中实例化和配置对象,如以下代码段所示:

// Load policies from the configuration file.
// SystemConfigurationSource is defined in 
// Microsoft.Practices.EnterpriseLibrary.Common.
using (var config = new SystemConfigurationSource())
{
  var settings = RetryPolicyConfigurationSettings.GetRetryPolicySettings(config);

  // Initialize the RetryPolicyFactory with a RetryManager built from the 
  // settings in the configuration file.
  RetryPolicyFactory.SetRetryManager(settings.BuildRetryManager());

  var retryPolicy = RetryPolicyFactory.GetRetryPolicy
  <SqlDatabaseTransientErrorDetectionStrategy>("Incremental Retry Strategy");   
   ... 
   // Use the policy to handle the retries of an operation.

}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请访问文档.


Chi*_*ani 5

所有与远程服务通信的应用程序都对瞬时故障很敏感。

如其他答案中所述,如果您的客户端程序使用 .NET Framework 类 System.Data.SqlClient.SqlConnection 连接到 SQL 数据库,请使用 .NET 4.6.1 或更高版本(或 .NET Core),以便您可以使用其连接重试功能。

为 SqlConnection 对象构建连接字符串时,请协调以下参数之间的值:

ConnectRetryCount:默认值为 1。范围为 0 到 255。

ConnectRetryInterval:默认为 1 秒。范围是 1 到 60。

连接超时:默认为 15 秒。范围是 0 到 2147483647。

具体来说,您选择的值应该使以下等式成立:

Connection Timeout = ConnectRetryCount * ConnectionRetryInterval
Run Code Online (Sandbox Code Playgroud)

现在,转到选项 2,当您的应用程序具有自定义重试逻辑时,它将增加总重试次数 - 对于每次自定义重试,它将尝试 ConnectRetryCount 次。例如,如果 ConnectRetryCount = 3 和自定义重试 = 5,它将尝试 15 次。您可能不需要那么多重试。

如果您只考虑自定义重试与连接超时:

连接超时的发生通常是由于网络有损 - 数据包丢失较高的网络(例如蜂窝或弱 WiFi)或高流量负载。这取决于您选择使用它们的最佳策略。

以下指南将有助于解决瞬态错误:

  1. https://docs.microsoft.com/en-us/azure/sql-database/sql-database-connectivity-issues

  2. https://docs.microsoft.com/en-in/azure/architecture/best-practices/transient-faults