2013-04-23 18 views
16

Mam następujący kod do testowania połączenia DB, działa okresowo do testowania DB Dostępność:Jak sprawdzić dostępność bazy

private bool CheckDbConn() 
{ 
    SqlConnection conn = null; 
    bool result = true; 

    try 
    { 
     conn = DBConnection.getNewCon(); 
     ConnectionState conState = conn.State; 

     if (conState == ConnectionState.Closed || conState == ConnectionState.Broken) 
     { 
      logger.Warn(LogTopicEnum.Agent, "Connection failed in DB connection test on CheckDBConnection"); 
      return false; 
     }    
    } 
    catch (Exception ex) 
    { 
     logger.Warn(LogTopicEnum.Agent, "Error in DB connection test on CheckDBConnection", ex); 
     return false; // any error is considered as db connection error for now 
    } 
    finally 
    { 
     try 
     { 
     if (conn != null) 
     { 
      conn.Close(); 
     } 
     } 
     catch (Exception ex) 
     { 
     logger.Warn(LogTopicEnum.Agent, "Error closing connection on CheckDBConnection", ex); 
     result = false; 
     } 
    } 
    return result; 
} 

oraz:

static public SqlConnection getNewCon() 
{ 
    SqlConnection newCon = new SqlConnection(); 
    newCon.ConnectionString = DBConnection.ConnectionString; // m_con.ConnectionString; 
    newCon.Open(); 
    return newCon; 
} 

Moje pytanie brzmi: czy to działać zgodnie z oczekiwaniami?

W szczególności jestem zaniepokojony aobut testu ConnectionState. Czy to możliwe, że stan będzie: łączenie (od Open() jest synchroniczne)?

Co należy zrobić w takim przypadku?

Z góry dziękuję, Omer

Odpowiedz

32

Możesz spróbować w ten sposób.

public bool IsServerConnected() 
    { 
     using (var l_oConnection = new SqlConnection(DBConnection.ConnectionString)) 
     { 
      try 
      { 
       l_oConnection.Open(); 
       return true; 
      } 
      catch (SqlException) 
      { 
       return false; 
      } 
     } 
    } 
+0

co jeśli l_oConnection.Close(); rzuci wyjątek w bloku finally? –

+1

używając ... zamknij i wyrzuć połączenie, nie trzeba wtedy zamykać – Steve

+0

Używałem tego, ale stwierdziłem, że zwróciło ono wartość true podczas pierwszego wywołania po tym, jak baza danych została przejęta w trybie offline. To było przy użyciu .NET 3.5 przeciwko dbl serwera db 2012. – monty

9

SqlConnection rzuci SqlException gdy nie może połączyć się z serwerem.

public static class SqlExtensions 
{ 
    public static bool IsAvailable(this SqlConnection connection) 
    { 
     try 
     { 
      connection.Open(); 
      connection.Close(); 
     } 
     catch(SqlException) 
     { 
      return false; 
     } 

     return true; 
    } 
} 

Zastosowanie:

using(SqlConnection connection = GetConnection()) 
{ 
    if(connection.IsAvailable()) 
    { 
     // Success 
    } 
} 
8

Kod wydaje się w porządku, ale naprawdę trzeba używać IDisposable wzór, a niektóre konwencja nazewnictwa też:

private bool CheckDbConnection(string connectionString) 
{ 
    try 
    { 
     using(var connection = new SqlConnection(connectionString)) 
     { 
      connection.Open(); 
      return true; 
     } 
    } 
    catch (Exception ex) 
    { 
     logger.Warn(LogTopicEnum.Agent, "Error in DB connection test on CheckDBConnection", ex); 
     return false; // any error is considered as db connection error for now 
    } 
} 

I connection.Close() nie ma rzucać. Po prostu użyj bloku using, a twoje są w porządku.

Nie trzeba sprawdzać stanu Close, ponieważ właśnie go otworzyłeś.
More about the Broken state:

łamany Połączenie ze źródłem danych jest uszkodzony. Może się to zdarzyć tylko po otwarciu połączenia. Połączenie w tym stanie może zostać zamknięte, a następnie ponownie otwarte. (Ta wartość jest zarezerwowana dla przyszłych wersji produktu).

Tak naprawdę, nie ma potrzeby testowania tego.

Stan Connecting może zostać przechwycony, jeśli znajdujesz się w kontekście wielowątkowym, a twoja instancja połączenia jest współużytkowana. Ale to nie twoja sprawa tutaj.

0

nie mogę skomentować tak ...

... również uniknąć łapania ogólne wyjątki "catch (Exception ex)" i spróbować złapać szczególne wyjątki, jak w przykładach powyżej "catch (SQLException ex)"

0

w rzeczywistości, w visual studio, klasa połączenia ma właściwość sonnectionstate.

po zmianie stanu połączenia, zdarzenie statechange połączeń zostało zmienione.

możesz sprawdzić ten artykuł.

https://msdn.microsoft.com/en-us/library/aa326268(v=vs.71).aspx

+0

Nie jestem pewien, jak to jest związane ze studiem wizualnym, a jeśli spojrzysz na wpis, ma ono połączenie connectionState ... –

0

używałem rozwiązanie @Ramesh Durai, ale okazało się, że na mojej konfiguracji przynajmniej (aplikacja wywołujący/testowanie okresowo po aplikacja zaczęła; użyciu .NET 3.5 z SQL Server 2012 bazy danych), że pierwsza połączenie z IsConnected() po przejęciu bazy danych w tryb offline powróciło true. Jednak został rzucony oczekiwany wyjątek na linii ExecuteScalar() poniżej:

public bool IsConnected() { 
    using (var conn = new SqlConnection(DBConnection.ConnectionString)) { 
     using (var cmd = New SqlCommand("SELECT 1", conn)) { 
      try { 
       conn.Open(); 
       cmd.ExecuteScalar(); 
       return true; 
      } catch (SqlException) { 
       return false; 
      } 
     } 
    } 
} 
Powiązane problemy