2015-08-23 5 views
2

У меня есть метод, который возвращает, можно ли открыть соединение.Получить причину ошибки SqlConnection

Однако в случае отказа мне необходимо уведомить пользователей о том, предоставили ли они плохие учетные данные или были проблемы с базой данных.

Текущий код:

try 
{ 
    Database db = new SqlDatabase(connectionString); 
    using(var connection = db.CreateConnection()) 
    { 
     connection.Open(); 
     return true; 
    } 
} 
catch (Exception ex) 
{ 
    return false; 
} 

ли это проблема с учетными данными или базы данных, исключение всегда SqlException.

Однако, я заметил следующие отличия:

Неверные учетные данные:

  • Сообщение: Login failed for user 'whatever'
  • Класс: 14
  • Номер: 18456
  • Состояние: 1

Bad базы данных:

  • Сообщение: A network something or other
  • Класс: 20
  • Номер: -1
  • Состояние: 0

... Так что да, есть различия, но я не конечно, я могу положиться на эти цифры (и проверка строкового значения сообщения заставляет меня чувствовать, что мне нужно принять душ).

Согласно MSDN, то Number свойства может быть кодом ошибки Win32 или код ошибки сервера, Class обозначает серьезность и State может дать различным кодам ошибок разных значений.

Есть ли лучший способ определить сбой соединения?

ответ

4

Код ошибки сервера Sql: documented, и вы можете определенно полагаться на них!

3

Поскольку свойство Class относится к ошибке Severity об ошибке, о которой сообщает SQL Server, вы можете использовать ее для определения того, какое действие требуется.

Из таблицы серьезности SQL Server мы узнаем:

  • 11-16 указывают на ошибки, которые могут быть исправлены пользователем.
  • 14 Указывает на связанные с безопасностью ошибки, такие как отказ в доступе.
  • 20 Укажите системные проблемы и являются фатальными ошибками ...

Ваш метод может возвращать код состояния в зависимости от того, может ли серьезность быть зафиксирована пользователем или нет. Какие коды попадают в эту категорию до ваших конкретных требований, но вы можете себе представить, что-то вроде этого:

public enum Status 
    { 
     Success = 0, 
     None, 
     RetryUser, 
     RetryInfra, 
     Network, 
     Boom, 
     MAX 
    } 

    public Status ConnectionStatus() 
    { 
     Status status = Status.None; 

     try 
     { 
      Database db = new SqlDatabase(connectionString); 

      using (var connection = db.CreateConnection()) 
      { 
       connection.Open(); 
       status = Status.Success; 
      } 
     } 
     catch (SqlException ex) 
     { 
      switch (ex.Class) 
      { 
       case 11: 
       case 12: 
       case 13: 
       case 14: 
        status = Status.RetryUser; 
        break; 

       case 20: 
        status = Status.RetryInfra; 
        break; 

       default: 
        status = Status.Boom; 
        break; 
      } 
     } 

     return status; 
    } 

Из Understanding Database Engine Errors в MSDN мы узнаем, что State, вероятно, не является хорошим кандидатом, чтобы определить правильный следующий шаг:

Некоторые сообщения об ошибках могут быть подняты в нескольких точках кода для механизма базы данных. Например, ошибка 1105 может быть повышена для нескольких разных условий. Каждое конкретное условие, которое вызывает ошибку, присваивает уникальный код состояния.

+0

Хороший ответ, но это также должно обрабатывать такие вещи, как сетевые проблемы. – usr

+0

@usr Я предполагаю, что в этих случаях возникает исключение IOException, правильно? – rene

+0

Все SqlException. Для этого есть недокументированный код ошибки. – usr