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

C# 正确处理数据库连接问题的方法,c#,ado.net,azure-sql-database,sqlconnection,C#,Ado.net,Azure Sql Database,Sqlconnection,我在尝试连接数据库时遇到以下错误: 运行时发生与网络相关或特定于实例的错误 正在建立与SQL Server的连接。找不到服务器,或者 无法访问。验证实例名称是否正确,以及 SQL Server配置为允许远程连接。(提供者:已命名) 管道提供程序,错误:40-无法打开到SQL Server的连接) 现在,有时我会遇到这个错误,有时我不会,例如:当我第一次运行程序时,它成功地打开了连接,当我第二次运行时,我会遇到这个错误,下一次再次运行程序时,我不会遇到错误 当我尝试通过SSMS连接到同一个数据库服

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

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

现在,有时我会遇到这个错误,有时我不会,例如:当我第一次运行程序时,它成功地打开了连接,当我第二次运行时,我会遇到这个错误,下一次再次运行程序时,我不会遇到错误

当我尝试通过SSMS连接到同一个数据库服务器时,我能够成功连接,但我的程序中只出现了这个网络问题

数据库不在myLOCAL中。它位于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
                }
            }
        }
}
我对以上两个选项感到困惑

有谁能告诉我解决此问题的更好方法吗?

正如您所知,即使是安装在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);
// 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.

}
var retryStrategy=new Incremental(5,TimeSpan.FromSeconds(1),
时间跨度从秒(2)开始;
风险回报政策=
新RetryPolicy(retryStrategy);
在第二种方法中,您可以根据配置数据实例化和配置对象,如以下代码段所示:

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

var retryPolicy =
  new RetryPolicy<SqlDatabaseTransientErrorDetectionStrategy>(retryStrategy);
// 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.

}
//从配置文件加载策略。
//SystemConfigurationSource在中定义
//Microsoft.Practices.EnterpriseLibrary.Common。
使用(var config=new SystemConfigurationSource())
{
var settings=RetryPolicyConfigurationSettings.GetRetryPolicySettings(配置);
//使用从中生成的RetryManager初始化RetryPolicyFactory
//配置文件中的设置。
RetryPolicyFactory.SetRetryManager(settings.BuildRetryManager());
var retryPolicy=RetryPolicyFactory.GetRetryPolicy
(“增量重试策略”);
... 
//使用策略处理操作的重试。
}
有关详细信息,请访问文档。

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

ConnectRetryCount、ConnectRetryInterval和连接超时


有关更多信息,请参阅:

您使用的是SQL Express还是工作组版?如果是这样,可能是服务器太忙而无法响应

要排除网络问题,请在命令提示符下执行
PING-tsqlservername
。是每一个ping都回来了,还是有些丢失了?这可能是网络中断的指示器,也可能导致此错误,如故障交换机。如果它们都丢失了(考虑到您的数据库连接有时可以正常工作),那么ping很可能被某个地方的防火墙阻止了:如果您找到该阻止并临时取消阻止,这可能有助于诊断

错误消息表明您正在使用命名管道。您是否有意使用命名管道?对于大多数场景(包括Azure数据库),我建议在SQL Server Configuration Manager中启用TCP/IP并禁用命名管道


根据Azure数据库的“距离”,路由器和防火墙造成的延迟有时会打乱Kerberos和/或相关计时。您可以通过使用连接字符串中的端口来克服这一问题,以避免往返到端口1434来枚举实例。我假设您已经在使用FQDN。例如:服务器\例如,端口

连接完全可能断开。“分布式计算的谬误”:。 这可能是网络连接问题。可能在任何一端

我建议:(假设在Azure上为您的计算机启用了防火墙)

  • Ping服务器并查看是否有任何丢失
  • ping(服务器).database.windows.net

  • 示踪剂
  • telnet也可以是你的朋友
  • 以上三点可以帮助您确定问题所在

    我认为你的重试逻辑很好

    关于您的问题

    增加超时时间 只有在您确信查询将花费很长时间的情况下。若要进行简单的插入,必须增加超时时间,则可能是网络连接问题

    重试逻辑
    如前所述,它现在是框架的一部分,您可以使用它,或者您创建的框架应该可以使用。理想情况下,拥有重试逻辑是很好的,即使您对连接性和速度很确定。以防万一:)

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

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

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

    ConnectRetryCount:默认值为1。范围是0到255RetryPolicy retryPolicy = Policy.Handle<Exception>() .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt)); var result = retryPolicy.Execute(() => someClass.DoSomething());