Який найкращий спосіб перевірити підключення SQL Server програмно?


78

Мені потрібно розробити єдину процедуру, яка запускатиметься кожні 5 хвилин, щоб перевірити, чи працює та працює список SQL-серверів (від 10 до 12).

Я можу спробувати отримати простий запит на кожному із серверів, але це означає, що мені потрібно створити таблицю, перегляд або збережену процедуру на кожному сервері, навіть якщо я використовую будь-який вже створений ІП, мені потрібно мати зареєстрованого користувача на кожному сервер теж. Сервери знаходяться не в одному фізичному розташуванні, тому наявність цих вимог буде складним завданням. Чи є спосіб просто "пінгувати" з C # one SQL Server?

Спасибі заздалегідь!


2
Простого пінгування сервера буде недостатньо, можливо, що сервер працює, але екземпляр SQL зупиниться. Створення фактичного зв’язку ado.net із екземпляром - найкращий варіант.
Рорі

Чи знали ви, що у вас було єдине запитання на сайті mssqlз понад 1/2 мільйонів інших запитань? Ви справді вважаєте, що це хороший тег? Ви були тут досить довго, щоб краще знати.
Joel Coehoorn

2
Як ви знаєте, існує велика різниця між MS-SQL та SQL-сервером, особливо якщо ми говоримо про порти та їх пінгування. Яка демократія, кожен повинен використовувати один і той же тег. Без варіантів! Вам слід додати ще один тег без проблем, але навіщо виймати той, який я вибрав !!!!
зворотна коса риса 17

2
MS-SQL IS SQL Server - назва продукту IS SQL Server.
marc_s

8
SQL Server може посилатися на: - Будь-який сервер баз даних, який реалізує мову структурованих запитів - Microsoft SQL Server, конкретний сервер баз даних реалізації від Microsoft - Sybase SQL Server, реляційний сервер баз даних, розроблений Sybase. ------- Як бачите, для сервера SQL існує більше одного значення, і тому я використав тег MSSQL
backslash17

Відповіді:


75

Виконайте SELECT 1та перевірте, чи ExecuteScalar повертає 1.


1
Це дуже добре, не потрібно створювати будь-який об’єкт у базі даних, але мені потрібно мати базу даних та користувача, щоб зробити запит. Я просто хочу знати, чи працює служба в порту MSSQL. У будь-якому випадку, ви вирішуєте майже 75% проблеми. Це був би варіант.
зворотна коса риса 17

5
У вас і так є master db :) Найпростіший спосіб перевірити, чи працює SQL Server, - це підключення до нього. Для підключення вам потрібні db та логін. Усі інші рішення (наприклад, пінгування порту SQL Server) не гарантують, що SQL Server працює належним чином, і будь-хто може підключитися до нього.
Ендрю Беззуб

Я випадково проголосував за цю відповідь, тоді як моїм справжнім наміром було проголосувати. Я зрозумів це через день, тому більше не можу виправити свою помилку.
Giorgos Betsos

1
@GiorgosBetsos - Я виправив вашу помилку :-D
Kunal B.

80

У мене були труднощі з EF, коли підключення до сервера зупинено або призупинено, і я підняв те саме питання. Отже, для повноти наведених вище відповідей ось код.

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

14
connection.Close();в цьому випадку не потрібно , usingпункт буде робити це за вас після припинення дії.

3
Ви повинні поставити try catch за межі оператора using. ( stackoverflow.com/q/4590490/1248177 або stackoverflow.com/q/6145245/1248177 ).
aloisdg переїжджає на codidact.com

1
@aloisdg - Це залежить від цього, чи тестують вони, чи можуть вони підключитися до бази даних, і лише у виняткових обставинах вони не можуть повернути false. АБО хочу зробити так, щоб проковтнути винятки, пов’язані також з неправильним побудовою з’єднання SQL, я знаю, що є різниця, оскільки я щойно кодував проти вищезазначеного.
brumScouse

13

Дивіться наступний проект на 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);
}

7

Чи не зробить це для вас встановлення зв’язку з базою даних? Якщо база даних не працює, ви не зможете встановити з'єднання.


Дійсно, просто використовуйте ADO net для підключення - якщо відповіді немає протягом періоду очікування, база даних недоступна. Вам не потрібно видавати запит, щоб це встановити.
Dan Diplo

Для перевірки в ADO.NET мені потрібен користувач, я просто хочу перевірити, чи працює та працює служба, не виникає проблем з тим, чи працює база даних. Мені потрібно щось на зразок telnet, SMTP-сервер. Не потрібно мати користувача, щоб отримати відповідь.
зворотна коса риса 17

3
@ backslash17: Відповіді "Не вдалося ввійти користувачеві ..." має бути достатньо, щоб підтвердити, що 1) машина працює і 2) служба працює. Якщо ви отримуєте час очікування з’єднання, служба не працює / працює.
Рорі

@Rory: Гарна думка! Це лише питання перевірки помилки в блоці try / catch. Дякую!
зворотна коса риса 17

@ backslash17 Переконайтеся, що "Вхід користувача не вдався" має окремий код помилки або щось, що допомагає вам його визначити. Дуже погана практика відрізняти помилки за повідомленнями про виключення.
Ендрю Беззуб

1

Шукайте відкритий прослуховувач на порту 1433 (порт за замовчуванням). Якщо ви отримаєте будь-яку відповідь після створення там з'єднання tcp, сервер, ймовірно, працює.


Що з того, що запропонував Джоел Кехорн, ви вже пробували tcping [ elifulkerson.com/projects/tcping.php] . Це автономний виконуваний файл, який дозволяє пінгувати кожен вказаний інтервал часу. Однак це не в C #. Також..не впевнений, чи це спрацює, якщо цільова машина має брандмауер .. мммм ..
Ashish Gupta

1

На те, що запропонував Джоел Кехорн, ви вже пробували утиліту під назвою tcping . Я знаю, це те, що ви не робите програмно. Це автономний виконуваний файл, який дозволяє пінгувати кожен вказаний інтервал часу. Однак це не в C #. Крім того .. я не впевнений, чи це буде працювати, якщо цільова машина має брандмауер .. мммм ..

[Я якось новачок на цьому сайті і помилково додав це як коментар, а тепер додав це як відповідь. Повідомте мене, якщо це можна зробити тут, оскільки тут є дублікати коментарів (як коментар та відповідь). Я не можу видалити коментарі тут.]


1
public static class SqlConnectionExtension
{
    #region Public Methods

    public static bool ExIsOpen(
        this SqlConnection connection, MessageString errorMsg = null)
    {
        if (connection == null) { return false; }
        if (connection.State == ConnectionState.Open) { return true; }

        try
        {
            connection.Open();
            return true;
        }
        catch (Exception ex) { errorMsg?.Append(ex.ToString()); }
        return false;
    }

    public static bool ExIsReady(
        this SqlConnection connction, MessageString errorMsg = null)
    {
        if (connction.ExIsOpen(errorMsg) == false) { return false; }
        try
        {
            using (var command = new SqlCommand("select 1", connction))
            { return ((int)command.ExecuteScalar()) == 1; }
        }
        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

Подібно до відповіді, запропонованої Ендрю, але я використовую:

Виберіть GetDate () як CurrentDate

Це дозволяє мені зрозуміти, чи є у SQL Server та клієнта проблеми з різницею часових поясів в одній дії.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.