2009-12-18 12 views
1

J'ai une méthode pour vérifier et m'assurer que mon serveur SQL est en ligne, que j'utilise dans certaines parties sensibles de mon code.Comment puis-je vérifier si le serveur SQL est actif?

Bien que cela fonctionne bien, je remarque qu'il faut jusqu'à 20ms pour fonctionner, et je me demandais si quelqu'un connaît une meilleure façon de vérifier SQL Server pour assurer son up and kick.

Voici mon code existant.

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] 
     public static bool IsSqlServerOnline(string connectionString) 
     { 
#if DEBUG || DEBUG_SINGLE_CORE 
      Stopwatch sw = new Stopwatch(); 
      sw.Start(); 
#endif 

#if DEBUG || DEBUG_SINGLE_CORE 
      // This sould only occur of we are in the VSTS designer 
      if (string.IsNullOrEmpty(connectionString)) 
      { 
       return false; 
      } 
#endif 

      if (!NetworkInterface.GetIsNetworkAvailable()) 
      { 
       return false; 
      } 

      if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString"); 

      bool isSqlServerOnline = false; 
      SqlConnectionStringBuilder conString = new SqlConnectionStringBuilder(connectionString); 

      try 
      { 
       using (Ping p = new Ping()) 
       { 
        string sqlSvr = conString.DataSource; 
        if (sqlSvr != null) 
         isSqlServerOnline = p.Send(sqlSvr).Status == IPStatus.Success; 
       } 
      } 
      catch (PingException) 
      { 
       isSqlServerOnline = false; 
      } 

      if (isSqlServerOnline) 
      { 
       try 
       { 
        conString.ConnectTimeout = 3; 
        using (SqlConnection conn = new SqlConnection(conString.ToString())) 
        { 
         conn.Open(); 
         isSqlServerOnline = true; 
        } 
       } 
       catch (Exception) 
       { 
        isSqlServerOnline = false; 
       } 
      } 

#if DEBUG || DEBUG_SINGLE_CORE 
      sw.Stop(); 
      Trace.WriteLine(string.Format("IsSqlServerOnline: {0}", sw.ElapsedMilliseconds)); 
#endif 
      return isSqlServerOnline; 
     } 
+1

20ms est sacrément rapide; est-ce une partie significative de votre page fois, ou appelez-vous cela énormément? –

+0

20ms ne semble pas si mal. Considérez, vous faites une connexion, obtenez une réponse, et colmatez la connexion - partout dans le réseau. Je pense que vous aurez du mal à faire quelque chose plus vite ... mais je peux me tromper. – Nate

+0

20 ms n'est pas très long, surtout si vous êtes sur le réseau. –

Répondre

1

Comme d'autres l'ont mentionné, la barrière de 20 ms n'est probablement pas une source d'inquiétude. Cependant, je pourrais demander à quelle fréquence le code est appelé? Serait-il suffisant de mettre en cache le résultat de l'appel pendant 3-5 secondes (ou même seulement 2-3)? au lieu d'accéder au réseau à chaque fois? 2-3 secondes est une assez petite fenêtre de cache, et il n'y a rien à dire qu'un contrôle "serveur vivant" ne pourrait pas retourner OK seulement pour faire planter le serveur au milieu du code en cours d'exécution quand même. Si tout ce que vous gaspillez est de 20 ms toutes les quelques secondes (au maximum), cela ne vous inquiète guère.

+0

Typiquement, quand j'appelle ce code, il est appelé en morceaux, donc je reçois beaucoup d'appels, puis rien pendant un certain temps. J'aime votre idée de mise en cache, et j'ai mis dans un cache de 10 secondes, que je vais modifier en fonction des observations de production au fil du temps. On dirait que j'ai juste le temps d'environ 5ms en utilisant le cache juste après la vérification si le PC lui-même a un réseau disponible. – Russ

1

Vous pouvez utiliser l'API de gestionnaire de contrôle de service Windows:

  1. Appel OpenSCManager (a le nom d'hôte en tant que paramètre)
  2. Appel OpenService
  3. Appel QueryServiceStatus

Si l'état est SERVICE_RUNNING, le service est en place.

Si vous n'êtes pas dans P/Invoke, jetez un oeil à System.ServiceProcess.ServiceController. La fonction

public ServiceController(string name, string machineName) 

semble être utilisée pour récupérer l'état d'un service spécifique.

+0

J'utilise cette fonction dans d'autres parties de mon code, et j'ai constaté que si vous n'êtes pas un administrateur sur la boîte de votre appel, il va planter. – Russ

+0

Oui, vous avez besoin des droits d'administrateur pour contrôler les services. Je m'attends à ce qu'il renvoie ERROR_ACCESS_DENIED au lieu de se bloquer. En outre, les pare-feu peuvent bloquer les ports utilisés par ces appels de fonction – Andomar

+0

Vous avez probablement raison de renvoyer cette erreur, mais il le fait sous la forme d'une exception Win32Exception. Si non manipulé est un accident, et si handeled, dans ce cas, ne m'obtient pas où, parce que je ne saurai pas l'état du service de toute façon. – Russ

2

Votre code vérifie si vous êtes en mesure d'établir une connexion au serveur SQL. Vous pouvez également être intéressé à prendre un peu plus loin et vérifier qu'il répond aux requêtes en exécutant quelque chose comme

Select @@version 
Questions connexes