2010-03-13 14 views
50

Ich muss eine einzelne Routine entwickeln, die alle 5 Minuten abgefeuert wird, um zu überprüfen, ob eine Liste von SQL Servern (10 bis 12) läuft.Was ist der beste Weg, SQL Server-Verbindung programmgesteuert zu testen?

Ich kann versuchen, eine einfache Abfrage in jedem der Server zu erhalten, aber das bedeutet, dass ich eine Tabelle, Ansicht oder gespeicherte Prozedur in jedem Server erstellen muss, auch wenn ich einen bereits gemachten SP verwende ich muss registrierter Benutzer in jedem Server auch. Die Server befinden sich nicht am selben physischen Standort, sodass diese Anforderungen eine komplexe Aufgabe darstellen. Gibt es eine Möglichkeit, einfach von C# One SQL Server "Ping"?

Vielen Dank im Voraus!

+2

Einfaches Pingen des Servers wäre nicht genug, es ist möglich, dass der Server läuft, aber die SQL-Instanz gestoppt wird. Das Erstellen einer tatsächlichen ado.net-Verbindung zur Instanz ist die beste Option. – Rory

+0

Wusstest du, dass du die _only_ Frage auf der Seite mit "mssql" aus mehr als 1/2 Millionen anderen Fragen markiert hast? Glaubst du wirklich, dass das ein guter Tag ist? Du warst lange genug hier, um es besser zu wissen. –

+1

Wie Sie wissen, gibt es einen großen Unterschied zwischen MS-SQL und SQL-Server, speziell wenn wir über Ports sprechen und sie anpingen. Was für eine Demokratie, jeder muss den gleichen Tag benutzen. Keine Optionen! Du solltest ein weiteres Tag hinzufügen, kein Problem damit, aber warum soll ich das auswählen, das ich gewählt habe !!!! – backslash17

Antwort

52

SELECT 1 ausführen und überprüfen, ob ExecuteScalar 1.

+0

Das ist sehr gut, kein Objekt muss in einer Datenbank erstellt werden, aber ich brauche eine Datenbank und einen Benutzer, um eine Abfrage zu erstellen. Ich möchte nur wissen, ob der Dienst im MSSQL-Port ist. Wie auch immer, Sie lösen fast 75% des Problems. Dies wäre eine Option. – backslash17

+2

Sie haben Master-Datenbank trotzdem :) Der sauberste Weg, um zu überprüfen, ob SQL Server ausgeführt wird, ist eine Verbindung zu ihm. Um dich zu verbinden brauchst du db und loggst trotzdem. Alle anderen Lösungen (wie das Pingen des SQL Server-Ports) garantieren nicht, dass SQL Server ordnungsgemäß ausgeführt wird und dass jeder Benutzer eine Verbindung herstellen kann. –

7

Möchten Sie keine Verbindung zur Datenbank herstellen? Wenn die Datenbank nicht geöffnet ist, können Sie keine Verbindung herstellen.

+0

In der Tat, verwenden Sie einfach ADO net zum Verbinden - wenn es keine Antwort innerhalb der Zeitüberschreitung gibt, dann die Datenbank ist nicht verfügbar. Sie müssen keine Abfrage ausführen, um dies sicherzustellen. –

+0

Um mit ADO.NET zu überprüfen, brauche ich einen Benutzer, ich möchte nur überprüfen, ob der Dienst läuft, kein Problem, wenn eine Datenbank läuft. Ich brauche etwas wie Telnet einen SMTP-Server. Kein Benutzer muss eine Antwort erhalten. – backslash17

+3

@ backslash17: Die Antwort "Anmeldung fehlgeschlagen für Benutzer ..." sollte ausreichen, um zu bestätigen, dass 1) der Computer betriebsbereit ist und 2) der Dienst ausgeführt wird. Wenn Sie ein Verbindungstimeout erhalten, wird der Dienst nicht ausgeführt. – Rory

1

Geben Sie für einen offenen Hörer zurück auf Port 1433 (der Standard-Port). Wenn Sie nach dem Erstellen einer TCP-Verbindung eine Antwort erhalten, ist der Server wahrscheinlich aktiv.

+1

Dies wird keine 100% ige Antwort geben. –

+0

@Joel Coehorn: Für mich ist eine gute Antwort! Irgendein Beispiel dafür? – backslash17

+0

Für das, was Joel Coehorn vorgeschlagen hat, haben Sie bereits versucht, tcping [http://www.elifulkerson.com/projects/tcping.php]. Es ist eine eigenständige ausführbare Datei, mit der Sie jedes spezifizierte Zeitintervall pingen können. Es ist nicht in C# obwohl. Auch..ich bin mir nicht sicher, ob dies funktionieren würde Wenn der Zielrechner eine Firewall hat..hmmm .. –

1

Für was Joel Coehorn vorgeschlagen hat, haben Sie bereits das Dienstprogramm namens tcping versucht. Ich weiß, das ist etwas, was du programmatisch nicht machst. Es ist eine eigenständige ausführbare Datei, mit der Sie jedes spezifizierte Zeitintervall pingen können. Es ist nicht in C# obwohl. Auch .. Ich bin mir nicht sicher, ob dies funktionieren würde Wenn das Zielgerät Firewall hat .. hmmm ..

[Ich bin ein wenig neu auf dieser Website und irrtümlich als Kommentar hinzugefügt, nun hinzugefügt, dies als Antwort. Lass es mich wissen, wenn das hier gemacht werden kann, da ich doppelte Kommentare (als Kommentar und als Antwort) hier habe. Ich kann hier keine Kommentare löschen.]

0

Warum nicht einfach mit Telnet-Sitzung auf dem Sql-Server-Port verbinden. Wenn es verbindet, ist SQL-Server und glücklich, wenn nicht, du bist kein Glück.

Dieser andere StackOverflow post könnte ein guter Anfang sein.

EDIT: OK, jetzt habe gelesen, ich voll und ganz die anderen Beiträge dies die beste Lösung ... Immer noch nicht genau ist, wenn Sie nur den Port ping wollen ....

42

ich je hatte eine Schwierigkeit mit der EF, wenn die Verbindung der Server gestoppt oder pausiert ist, und ich die gleiche Frage gestellt. Also zur Vollständigkeit der obigen Antworten hier ist der Code.

/// <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

keine Notwendigkeit für die 'connection.Close();' in diesem Fall wird die 'using' -Klausel dafür tun Sie nach der Kündigung. –

+0

Absolut 100% korrekt HaLaBi – peterincumbria

+3

Sie sollten den try catch außerhalb der using-Anweisung setzen. (http://stackoverflow.com/q/4590490/1248177 oder http://stackoverflow.com/q/6145245/1248177). – aloisdg

10

Siehe folgende Projekt auf 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

Verbindung über C# zum MSSQL sehr problematisch ist.

Die Handles werden nicht konsistent sein, sobald wir verbinden, obwohl wir die Verbindung nach dem Verbinden schließen.

Ich habe irgendwo gelesen, es war .Net 4.0 Problem, und wenn Sie .Net 3.5 verwenden, sollte es in Ordnung sein.

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

Ähnlich wie die Antwort von Andrew angeboten, aber ich benutze:

Select GetDate() als Current

Dies erlaubt mir, zu sehen, ob der SQL Server und der Client eine beliebige Zeitzone Unterschied haben Probleme, in der gleichen Aktion.