2010-03-13 21 views
50

Necesito desarrollar una única rutina que se dispare cada 5 minutos para verificar si una lista de servidores SQL (10 a 12) está en funcionamiento.¿Cuál es la mejor manera de probar la conexión de SQL Server mediante programación?

puedo tratar de obtener una simple consulta en cada uno de los servidores, pero esto significa que tengo que crear una tabla, vista o procedimiento almacenado en cada servidor, incluso si utilizo cualquier SP ya hecha Necesito tener una usuario registrado en cada servidor también. Los servidores no están en la misma ubicación física, por lo que tener esos requisitos sería una tarea compleja. ¿Hay alguna manera de simplemente "hacer ping" desde C# one SQL Server?

¡Gracias de antemano!

+2

Simplemente haciendo ping al servidor no sería suficiente, es posible que el servidor se ejecute pero la instancia de SQL se detenga. Crear una conexión real de ado.net a la instancia es la mejor opción. – Rory

+0

¿Sabía que tenía la pregunta _only_ en el sitio etiquetada 'mssql' de más de 1/2 millón de preguntas? ¿De verdad crees que es una buena etiqueta? Has estado aquí el tiempo suficiente para saber mejor. –

+1

Como saben, existe una gran diferencia entre MS-SQL y SQL-server, especialmente si hablamos de puertos y hacemos ping. Qué democracia, todos tienen que usar la misma etiqueta. ¡Sin opciones! Deberías agregar otra etiqueta, no hay problema con eso, pero ¿por qué sacar la que yo elijo? – backslash17

Respuesta

52

Ejecutar SELECT 1 y comprobar si ExecuteScalar devuelve 1.

+0

Eso es muy bueno, no es necesario tener ningún objeto creado en una base de datos, pero necesito tener una base de datos y un usuario para hacer una consulta. Solo quiero saber si el servicio está en el puerto MSSQL. De todos modos, estás resolviendo casi el 75% del problema. Esta sería una opción. – backslash17

+2

Tiene master db de todos modos :) La forma más limpia de comprobar si SQL Server se está ejecutando es conectarlo. Para conectarte necesitas db e iniciar sesión de todos modos. Todas las demás soluciones (como el ping del puerto SQL Server) no garantizarán que SQL Server se esté ejecutando correctamente y que cualquiera pueda conectarse. –

7

¿No sería bueno establecer una conexión a la base de datos? Si la base de datos no está activada, no podrá establecer una conexión.

+0

De hecho, simplemente use ADO net para Connect - si no hay respuesta dentro del tiempo de espera, entonces la base de datos no está disponible. No necesita emitir una consulta para averiguarlo. –

+0

Para verificar con ADO.NET necesito un usuario, solo quiero verificar si el servicio está en funcionamiento, no hay problema si la base de datos está activa. Necesito algo como telnet un servidor SMTP. No es necesario tener un usuario para obtener una respuesta. – backslash17

+3

@ backslash17: La respuesta "Error de inicio de sesión para el usuario ..." debería ser suficiente para confirmar que 1) la máquina está funcionando y 2) el servicio se está ejecutando. Si obtiene un tiempo de espera de conexión, entonces el servicio no se está ejecutando/trabajando. – Rory

1

Look para una escucha abierta en el puerto 1433 (el puerto por defecto). Si obtiene alguna respuesta después de crear una conexión de tcp allí, el servidor probablemente esté activo.

+1

Esto no dará 100% de respuesta. –

+0

@Joel Coehorn: ¡Para mí es una buena respuesta! ¿Algún ejemplo sobre eso? – backslash17

+0

Por lo que Joel Coehorn sugirió, ya ha intentado hacer tcping [http://www.elifulkerson.com/projects/tcping.php]. Es un ejecutable independiente que le permite hacer ping cada intervalo de tiempo especificado. Sin embargo, no está en C#. Además ... No estoy seguro si esto funcionaría Si la máquina de destino tiene cortafuegos ... mmm ... –

1

Por lo que Joel Coehorn sugirió, ya ha probado la utilidad llamada tcping. Sé que esto es algo que no estás haciendo programáticamente. Es un ejecutable independiente que le permite hacer ping cada intervalo de tiempo especificado. Sin embargo, no está en C#. Además ... No estoy seguro si esto funcionaría Si la máquina objetivo tiene cortafuegos ... mmm ...

[Soy un poco nuevo en este sitio y, erróneamente, lo agregué como comentario, ahora lo agregué como respuesta. Avíseme si esto se puede hacer aquí ya que tengo comentarios duplicados (como comentario y como respuesta) aquí. No puedo eliminar comentarios aquí.]

0

¿Por qué no simplemente conectarse a la sesión de telnet en el puerto del servidor sql. Si se conecta, el servidor sql está listo y feliz, si no, no tienes suerte.

Este otro StackOverflow post podría ser un buen lugar para comenzar con eso.

EDIT: OK, ahora que he leído completamente los otros mensajes que esto no es exactamente la mejor solución ... Sin embargo, si lo que desea hacer ping en el puerto ....

42

que he tenido una dificultad con el EF cuando la conexión del servidor está detenida o en pausa, y planteé la misma pregunta. Entonces, para completar las respuestas anteriores, aquí está el código.

/// <summary> 
/// Test that the server is connected 
/// </summary> 
/// <param name="connectionString">The connection string</param> 
/// <returns>true if the connection is opened</returns> 
private static bool IsServerConnected(string connectionString) 
{ 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     try 
     { 
      connection.Open(); 
      return true; 
     } 
     catch (SqlException) 
     { 
      return false; 
     } 
    } 
} 
+9

sin necesidad de 'connection.Close();' en este caso, la cláusula 'using' lo hará por usted en la terminación. –

+0

Absolutamente 100% correcto HaLaBi – peterincumbria

+3

Debe poner el try catch fuera de la instrucción using. (http://stackoverflow.com/q/4590490/1248177 o http://stackoverflow.com/q/6145245/1248177). – aloisdg

10

Véase el siguiente proyecto en GitHub: https://github.com/ghuntley/csharp-mssql-connectivity-tester

try 
{ 
    Console.WriteLine("Connecting to: {0}", AppConfig.ConnectionString); 
    using (var connection = new SqlConnection(AppConfig.ConnectionString)) 
    { 
     var query = "select 1"; 
     Console.WriteLine("Executing: {0}", query); 

     var command = new SqlCommand(query, connection); 

     connection.Open(); 
     Console.WriteLine("SQL Connection successful."); 

     command.ExecuteScalar(); 
     Console.WriteLine("SQL Query execution successful."); 
    } 
} 
catch (Exception ex) 
{ 
    Console.WriteLine("Failure: {0}", ex.Message); 
} 
-3

Conexión a mssql a través de C# es muy problemática.

Las asas no serán consistentes una vez que conectamos, aunque tenemos cerrar la conexión después de la conexión.

Lo leí en algún lugar que era .NET 4.0 problema, y ​​si utiliza .Net 3.5 debería estar bien.

0
public static class SqlConnectionExtension 
{ 
    #region Public Methods 

    public static bool ExIsOpen(this SqlConnection connection, MessageString errorMsg) 
    { 
     if (connection == null) return false; 
     if (connection.State != ConnectionState.Open) 
     { 
      try 
      { 
       connection.Open(); 
      } 
      catch (Exception ex) { errorMsg.Append(ex.ToString()); } 
     } 
     return true; 
    } 

    public static bool ExIsReady(this SqlConnection connction, MessageString errorMsg) 
    { 
     if (ExIsOpen(connction, errorMsg) == false) return false; 
     try 
     { 
      using (SqlCommand command = new SqlCommand("select 1", connction)) 
      using (SqlDataReader reader = command.ExecuteReader()) 
       if (reader.Read()) return true; 
     } 
     catch (Exception ex) { errorMsg.Append(ex.ToString()); } 
     return false; 
    } 

    #endregion Public Methods 
} 



public class MessageString : IDisposable 
{ 
    #region Protected Fields 

    protected StringBuilder _messageBuilder = new StringBuilder(); 

    #endregion Protected Fields 

    #region Public Constructors 

    public MessageString() 
    { 
    } 

    public MessageString(int capacity) 
    { 
     _messageBuilder.Capacity = capacity; 
    } 

    public MessageString(string value) 
    { 
     _messageBuilder.Append(value); 
    } 

    #endregion Public Constructors 

    #region Public Properties 

    public int Length { 
     get { return _messageBuilder.Length; } 
     set { _messageBuilder.Length = value; } 
    } 

    public int MaxCapacity { 
     get { return _messageBuilder.MaxCapacity; } 
    } 

    #endregion Public Properties 

    #region Public Methods 

    public static implicit operator string(MessageString ms) 
    { 
     return ms.ToString(); 
    } 

    public static MessageString operator +(MessageString ms1, MessageString ms2) 
    { 
     MessageString ms = new MessageString(ms1.Length + ms2.Length); 
     ms.Append(ms1.ToString()); 
     ms.Append(ms2.ToString()); 
     return ms; 
    } 

    public MessageString Append<T>(T value) where T : IConvertible 
    { 
     _messageBuilder.Append(value); 
     return this; 
    } 

    public MessageString Append(string value) 
    { 
     return Append<string>(value); 
    } 

    public MessageString Append(MessageString ms) 
    { 
     return Append(ms.ToString()); 
    } 

    public MessageString AppendFormat(string format, params object[] args) 
    { 
     _messageBuilder.AppendFormat(CultureInfo.InvariantCulture, format, args); 
     return this; 
    } 

    public MessageString AppendLine() 
    { 
     _messageBuilder.AppendLine(); 
     return this; 
    } 

    public MessageString AppendLine(string value) 
    { 
     _messageBuilder.AppendLine(value); 
     return this; 
    } 

    public MessageString AppendLine(MessageString ms) 
    { 
     _messageBuilder.AppendLine(ms.ToString()); 
     return this; 
    } 

    public MessageString AppendLine<T>(T value) where T : IConvertible 
    { 
     Append<T>(value); 
     AppendLine(); 
     return this; 
    } 

    public MessageString Clear() 
    { 
     _messageBuilder.Clear(); 
     return this; 
    } 

    public void Dispose() 
    { 
     _messageBuilder.Clear(); 
     _messageBuilder = null; 
    } 

    public int EnsureCapacity(int capacity) 
    { 
     return _messageBuilder.EnsureCapacity(capacity); 
    } 

    public bool Equals(MessageString ms) 
    { 
     return Equals(ms.ToString()); 
    } 

    public bool Equals(StringBuilder sb) 
    { 
     return _messageBuilder.Equals(sb); 
    } 

    public bool Equals(string value) 
    { 
     return Equals(new StringBuilder(value)); 
    } 

    public MessageString Insert<T>(int index, T value) 
    { 
     _messageBuilder.Insert(index, value); 
     return this; 
    } 

    public MessageString Remove(int startIndex, int length) 
    { 
     _messageBuilder.Remove(startIndex, length); 
     return this; 
    } 

    public MessageString Replace(char oldChar, char newChar) 
    { 
     _messageBuilder.Replace(oldChar, newChar); 
     return this; 
    } 

    public MessageString Replace(string oldValue, string newValue) 
    { 
     _messageBuilder.Replace(oldValue, newValue); 
     return this; 
    } 

    public MessageString Replace(char oldChar, char newChar, int startIndex, int count) 
    { 
     _messageBuilder.Replace(oldChar, newChar, startIndex, count); 
     return this; 
    } 

    public MessageString Replace(string oldValue, string newValue, int startIndex, int count) 
    { 
     _messageBuilder.Replace(oldValue, newValue, startIndex, count); 
     return this; 
    } 

    public override string ToString() 
    { 
     return _messageBuilder.ToString(); 
    } 

    public string ToString(int startIndex, int length) 
    { 
     return _messageBuilder.ToString(startIndex, length); 
    } 

    #endregion Public Methods 
} 
0

Similar a la respuesta ofrecida por Andrew, pero yo uso:

Seleccionar GetDate() como CurrentDate

Esto me permite ver si el SQL Server y el cliente tienen ninguna diferencia de zona horaria problemas, en la misma acción.

Cuestiones relacionadas