Wie kann die SQL Server-Verbindung am besten programmgesteuert getestet werden?

78

Ich muss eine einzelne Routine entwickeln, die alle 5 Minuten ausgelöst wird, um zu überprüfen, ob eine Liste von SQL-Servern (10 bis 12) aktiv ist.

Ich kann versuchen, auf jedem Server eine einfache Abfrage zu erhalten. Dies bedeutet jedoch, dass ich auf jedem Server eine Tabelle, eine Ansicht oder eine gespeicherte Prozedur erstellen muss, auch wenn ich einen bereits erstellten SP verwende, muss auf jedem Server ein registrierter Benutzer vorhanden sein Server auch. Die Server befinden sich nicht am selben physischen Standort, daher wäre es eine komplexe Aufgabe, diese Anforderungen zu erfüllen. Gibt es eine Möglichkeit, einfach von C # one SQL Server aus zu "pingen"?

Danke im Voraus!

Backslash17
quelle
2
Ein Ping des Servers würde nicht ausreichen. Möglicherweise wird der Server ausgeführt, aber die SQL-Instanz wird gestoppt. Das Erstellen einer tatsächlichen ado.net-Verbindung zur Instanz ist die beste Option.
Rory
Wussten Sie, dass Sie die einzige Frage auf der Website hatten, mssqldie von mehr als einer halben Million anderer Fragen markiert wurde? Glaubst du wirklich, dass das ein guter Tag ist? Sie sind schon lange genug hier, um es besser zu wissen.
Joel Coehoorn
2
Wie Sie wissen, gibt es einen großen Unterschied zwischen MS-SQL und SQL-Server, insbesondere wenn wir über Ports sprechen und sie anpingen. Was für eine Demokratie, jeder muss das gleiche Etikett verwenden. Keine Optionen! Sie sollten ein weiteres Tag hinzufügen, kein Problem damit, aber warum das herausnehmen, das ich wähle !!!!
Backslash17
2
MS-SQL IS SQL Server - Der Produktname ist IS SQL Server.
marc_s
8
SQL Server kann sich beziehen auf: - jeden Datenbankserver, der die strukturierte Abfragesprache implementiert - Microsoft SQL Server, einen bestimmten Implementierungsdatenbankserver von Microsoft - Sybase SQL Server, einen von Sybase entwickelten relationalen Datenbankserver. ------- Wie Sie sehen können, gibt es mehr als eine Bedeutung für SQL Server und deshalb habe ich das MSSQL-Tag verwendet
backslash17

Antworten:

75

Ausführen SELECT 1und prüfen, ob ExecuteScalar 1 zurückgibt.

Andrew Bezzub
quelle
1
Das ist sehr gut, es muss kein Objekt in einer Datenbank erstellt werden, aber ich benötige eine Datenbank und einen Benutzer, um eine Abfrage durchzuführen. Ich möchte nur wissen, ob der Dienst im MSSQL-Port aktiv ist. Wie auch immer, Sie lösen fast 75% des Problems. Dies wäre eine Option.
Backslash17
5
Sie haben sowieso Master-Datenbank :) Der sauberste Weg, um zu überprüfen, ob SQL Server ausgeführt wird, ist die Verbindung zu ihm. Um eine Verbindung herzustellen, benötigen Sie trotzdem db und login. Alle anderen Lösungen (wie das Pingen des SQL Server-Ports) garantieren nicht, dass SQL Server ordnungsgemäß ausgeführt wird und jeder eine Verbindung herstellen kann.
Andrew Bezzub
Ich habe diese Antwort versehentlich abgelehnt, während meine eigentliche Absicht darin bestand, zu stimmen. Ich habe das einen Tag später bemerkt, also kann ich meinen Fehler nicht mehr beheben.
Giorgos Betsos
1
@GiorgosBetsos - Ich habe Ihren Fehler behoben :-D
Kunal B.
80

Ich hatte Probleme mit der EF, als die Verbindung zum Server gestoppt oder unterbrochen wurde, und habe dieselbe Frage aufgeworfen. Der Vollständigkeit halber finden Sie hier den 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;
        }
    }
}
Peterincumbria
quelle
14
connection.Close();In diesem Fall ist dies nicht erforderlich. Die usingKlausel erledigt dies bei Kündigung für Sie.
3
Sie sollten den try catch außerhalb der using-Anweisung setzen. ( stackoverflow.com/q/4590490/1248177 oder stackoverflow.com/q/6145245/1248177 ).
Aloisdg wechselt zu codidact.com
1
@aloisdg - Es kommt darauf an, nicht wahr? Testen sie, ob sie eine Verbindung zu einer Datenbank herstellen können, und geben sie nur in Ausnahmefällen false zurück. ODER wollen Sie Ausnahmen schlucken, um eine SQL-Verbindung auch falsch aufzubauen? Ich weiß, dass es einen Unterschied gibt, da ich gerade gegen die oben genannten codiert habe.
brumScouse
13

Siehe das 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);
}
Geoffrey Huntley
quelle
7

Würde dies nicht für Sie eine Verbindung zur Datenbank herstellen? Wenn die Datenbank nicht aktiv ist, können Sie keine Verbindung herstellen.

Ken Henderson
quelle
Verwenden Sie einfach ADO net, um eine Verbindung herzustellen. Wenn innerhalb des Zeitlimits keine Antwort erfolgt, ist die Datenbank nicht verfügbar. Sie müssen keine Abfrage stellen, um dies festzustellen.
Dan Diplo
Um mit ADO.NET zu überprüfen, benötige ich einen Benutzer. Ich möchte nur überprüfen, ob der Dienst aktiv ist. Kein Problem, ob eine Datenbank aktiv ist. Ich brauche so etwas wie Telnet einen SMTP-Server. Sie müssen keinen Benutzer haben, um eine Antwort zu erhalten.
Backslash17
3
@ backslash17: Die Antwort "Anmeldung für Benutzer fehlgeschlagen ..." sollte ausreichen, um zu bestätigen, dass 1) der Computer aktiv ist und 2) der Dienst ausgeführt wird. Wenn Sie ein Verbindungszeitlimit erhalten, wird der Dienst nicht ausgeführt / funktioniert nicht.
Rory
@ Rory: Guter Punkt! Es geht nur darum, den Fehler in einem Try / Catch-Block zu überprüfen. Vielen Dank!
Backslash17
@ backslash17 Überprüfen Sie, ob "Anmeldung für Benutzer fehlgeschlagen" einen separaten Fehlercode enthält oder etwas, das Ihnen bei der Ermittlung hilft. Es ist sehr schlecht, Fehler nach Ausnahmemeldungen zu unterscheiden.
Andrew Bezzub
1

Suchen Sie nach einem offenen Listener an Port 1433 (dem Standardport). Wenn Sie nach dem Erstellen einer TCP-Verbindung eine Antwort erhalten, ist der Server wahrscheinlich in Betrieb.

Joel Coehoorn
quelle
Für das, was Joel Coehorn vorgeschlagen, haben Sie bereits versucht TCPing [ elifulkerson.com/projects/tcping.php] . Es ist eine eigenständige ausführbare Datei, mit der Sie jedes angegebene Zeitintervall anpingen können. Es ist jedoch nicht in C #. Ich bin mir nicht sicher, ob dies funktionieren würde, wenn der Zielcomputer eine Firewall hat. Hmmm.
Ashish Gupta
1

Für das, was Joel Coehorn vorgeschlagen, haben Sie bereits das Programm mit dem Namen versucht TCPing . Ich weiß, dass Sie dies nicht programmgesteuert tun. Es ist eine eigenständige ausführbare Datei, mit der Sie jedes angegebene Zeitintervall anpingen können. Es ist jedoch nicht in C #. Ich bin mir nicht sicher, ob dies funktionieren würde, wenn der Zielcomputer eine Firewall hat.

[Ich bin ein bisschen neu auf dieser Seite und habe dies fälschlicherweise als Kommentar hinzugefügt, jetzt als Antwort. Lassen Sie mich wissen, ob dies hier möglich ist, da ich hier doppelte Kommentare (als Kommentar und als Antwort) habe. Ich kann hier keine Kommentare löschen.]

Ashish Gupta
quelle
1
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
}
Endgültiger Himmel
quelle
0

Ähnlich der Antwort von Andrew, aber ich benutze:

Wählen Sie GetDate () als CurrentDate

Auf diese Weise kann ich in derselben Aktion feststellen, ob SQL Server und Client Probleme mit Zeitzonenunterschieden haben.

JustDaveN
quelle