2016-07-07 1 views
1

Я пытаюсь настроить метод, который попытается подключиться к SQL Server сначала на порт по умолчанию (1433) и затем на другой порт, например 7777 после сбоя.Настройка метода C#, пытающегося повторно подключиться к SQL Server на другом порту после первого отказа

Я хочу, чтобы избежать перестроения строки подключения и попытки подключения снова в случае сбоя, потому что этот метод будет выполнен с заданным интервалом, и я хочу как можно скорее устранить как можно больше накладных расходов.

Я попробовал следующее (любезно ConnectionStrings)

public void EstablishConnection() 
{ 
    string ConnectionString = "Data Source=127.0.0.1; Failover Partner=127.0.0.1,7777; Initial Catalog=foo;Connection Timeout = 3; Persist Security Info =True;User ID=<id>;Password=<password>"; 

    try 
    { 
     SqlConnection Connection = new SqlConnection(ConnectionString); 
     Connection.Open(); 
    } 
    catch (SqlException) 
    { 
     // Connection failed 
    } 
} 

Но, исходя от этого article и моего тестирования, он не работает так, как я предполагал.

Я мог бы легко решить эту проблему, выполнив следующие действия:

public void EstablishConnection() 
{ 
    string ConnectionString = "Data Source=127.0.0.1;Initial Catalog=foo;Connection Timeout = 3; Persist Security Info =True;User ID=<id>;Password=<password>"; 

    try 
    { 
     SqlConnection Connection = new SqlConnection(ConnectionString); 
     Connection.Open(); 
    } 
    catch (SqlException) 
    { 
     try 
     { 
      string ConnectionString = "Data Source=127.0.0.1,7777;Initial Catalog=foo;Connection Timeout = 3; Persist Security Info =True;User ID=<id>;Password=<password>"; 
      SqlConnection Connection = new SqlConnection(ConnectionString); 
      Connection.Open(); 
     } 
     catch (SqlException) 
     { 
      // Connection failed 
     } 
    } 
} 

Но это чувствует, как спагетти кода и общей плохой практикой.

Также в реальном приложении я не получаю полную строку подключения из файла конфигурации, я вытаскиваю параметры из файла конфигурации и строю строку конфигурации.

+0

У вас есть зеркальный сервер? – jdweng

+0

Нет идеи, что у меня было, если бы она не подключилась к ней на 1433, она перешла бы к серверу «Сбой по серверу», который является тем же сервером на другом порту. – Wamadahama

+0

Каждый экземпляр SQL Server имеет только один порт. Нужно больше, чем один экземпляр сервера sql. – jdweng

ответ

3

Прежде всего давайте определим вспомогательный метод для создания и открытия соединения пытаются все данные портов:

private SqlConnection TryEstabilishConnection(params int?[] portNumbers) { 
    foreach (int? portNumber in portNumbers) 
    { 
     var connectionString = CreateConnectionStringBuilder(); 
     if (portNumber != null) 
      connectionString.DataSource += $",{portNumber}"; 

     try { 
      var connection = new SqlConnection(connectionString.ToString()); 
      connection.Open(); 

      return connection; 
     } 
     catch (SqlException) { 
      // Attempt failed, log? 
     } 
    } 

    // Connection failed with all given ports... 
    return null; 
} 

CreateConnectionStringBuilder() метод считывает параметры из конфигурации и возвращает готовый к использованию SqlConnectionStringBuilder объекта:

private SqlConnectionStringBuilder CreateConnectionStringBuilder() { 
    // ... 
} 

Ваш код будет тогда:

public void EstabilishConnection() { 
    // You can specify more than one alternative port 
    var connection = TryEstabilishConnection(null, 7777, 58900); 
    if (connection == null) { 
     // Oops! 
    } 
} 

Обратите внимание, что если вы не укажете номер порта, он будет пытаться с невыполнением один (1433), но и попробовать UDP соединение с 1434 до спросить в течение динамически назначаемого TCP-порт (тогда альтернативных портов идеи полезна только если этот механизм отключен в конфигурации SQL Server).

отметить также, что иногда соединение не работает из-за связанные сетевые ошибки, но экземпляр SQL Server прослушивает порт по умолчанию, вы можете использовать повторные попытки шаблона, я просто очертить код здесь:

private SqlConnection TryEstabilishConnection(params int?[] portNumbers) { 
    foreach (int? portNumber in portNumbers) { 
     var connectionString = CreateConnectionStringBuilder(); 
     if (portNumber != null) 
      connectionString.DataSource += $",{portNumber}"; 

     var connection = TryEstabilishConnection(connectionString.ToString()); 
     if (connection != null) 
      return connection; 
    } 

    // Connection failed with all given ports... 
    return null; 
} 

private SqlConnection TryEstabilishConnection(string connectionString) { 
    for (int i=0; i < RetriesOnError; ++i) { 
     try { 
      var connection = new SqlConnection(connectionString); 
      connection.Open(); 

      return connection; 
     } 
     catch (SqlException) when (i < RetriesOnError - 1) { 
      Thread.Sleep(DelayBeforeRetry); 
     } 
    } 

    return null; 
} 

Эти константы являются лишь ориентировочными, сетевые ошибки могут потребовать более длительных задержек (или большего числа попыток), но вам, возможно, придется долго ждать слишком долго, прежде чем вы получите уведомление о том, что соединение недоступно (и если это часто происходит, должен изменить ваш UX, чтобы информировать пользователя о том, что происходит):

private const int RetriesOnError = 5; 
private const int DelayBeforeRetry = 1000; 

Код вызова не изменился. Вы можете использовать тот же шаблон также для повторной попытки во время обычных операций, см. Также Know when to retry or fail when calling SQL Server from C#?. В этом случае я предлагаю сохранить соединение, которое работало, чтобы не попробовать снова с портом по умолчанию, если он недоступен.

Очень последняя нота: Failover Partner (должно) работает только для зеркальных баз данных, AFAIK это не альтернативаData Source вы можете использовать без какой-либо другой конфигурации SQL Server (но я бы сказал, что это может быть хорошо бы иметь особенность).

 Смежные вопросы

  • Нет связанных вопросов^_^