Когда вызывается DbConnection.StateChange?

У меня есть следующий код:

   class Program
{
    static void Main()
    {
        var connection = new SqlConnection("myConnectionString");
        connection.Open();
        connection.StateChange += HandleSqlConnectionDrop;
        Console.WriteLine("Hi");
        Console.ReadLine();
    }

    private static void HandleSqlConnectionDrop(object connection, StateChangeEventArgs args)
    {
        Console.WriteLine("DB change detected");
    }
}

Я запускаю вышеуказанный код, пока экземпляр SQL-сервера запущен. Затем я перехожу к выполнению

SHUTDOWN WITH NOWAIT;

на сервере SQL Server, к которому подключена программа. Затем я наблюдаю остановку службы SQL-сервера. Тем не менее, я никогда не вижу сообщение "обнаружено изменение БД" на выходе. Почему это?

Помимо этого: Я увижу, что обработчик StateChange вызывается, если я затем попытаюсь выполнить операцию над соединением SQL, но никогда раньше. Есть ли способ изменить это поведение?

Ответ 1

Когда DbConnection.StateChange называется?

Вы можете узнать, посмотрев исходный код ссылки Microsoft.

Событие StateChange вызвано функцией DbConnection.OnStateChange. Поиск ссылок на эту функцию дает только несколько экземпляров:

Во-первых, в классе SqlConnection OnStateChange вызывается только в Close.

Затем в файле DbConnectionHelper.cs есть частичный класс под названием DBCONNECTIONOBJECT. Похоже, что он использовался для всех DbConnection -пределенных классов, используя некоторые махинации времени сборки. Поэтому вы можете считать его частью SqlConnection. В любом случае он вызывает OnStateChange только из SetInnerConnectionEvent.

Насколько я могу судить (частичная бессмыслица класса затрудняет), SqlConnection.SetInnerConnectionEvent вызывается только из SqlConnectionFactory.SetInnerConnectionEvent. И это вызвано из:

Итак, в итоге - событие возникает только в ответ на действия на стороне клиента - не возникает опроса состояния подключения, встроенного в SqlConnection.

Можно ли изменить это поведение?

Глядя на исходный код, я не вижу его. Как и другие, вы могли бы реализовать свой собственный опрос, конечно.

Ответ 2

Событие StateChange предназначено для состояния соединения, а не для экземпляра сервера базы данных. Чтобы получить состояние сервера базы данных,

Событие StateChange происходит, когда состояние события изменяется с закрыт для открытия или открыт для закрытия.

Из MSDN: https://msdn.microsoft.com/en-us/library/system.data.common.dbconnection.statechange(v=vs.110).aspx

Если вы собираетесь катить собственный монитор для базы данных, вы можете использовать метод, который возвращает true/false, если соединение доступно, и пинг этого метода по расписанию. Вы можете даже обернуть метод, чтобы сделать это в бесконечном цикле, повторяющемся после продолжительности времени, и поднять его собственное событие, когда это "состояние" действительно изменится.

Здесь быстрый метод из другого ответа SO, который является простым подходом:

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

Источник: fooobar.com/info/111350/...