Ошибка SqlDependency через долгое время
Я получил службу Windows, слушающую вставки в таблицу, используя класс SqlDependency.
Работает нормально несколько дней, а потом вдруг перестает работать.
В обычном сценарии я получаю изменения событий
e.Type = SqlNotificationType.+ Изменить
e.Info = SqlNotificationInfo.Вставить
e.Source = SqlNotificationSource.Данные
Если ничего не меняется, я получаю события тайм-аута каждые 3600 секунд
e.Type = SqlNotificationType.+ Изменить
e.Info = SqlNotificationInfo.ошибка
e.Source = SqlNotificationSource.Тайм-аут
или (не знаю, почему есть два разных события тайм-аута)
e.Type = SqlNotificationType.+ Изменить
e.Info = SqlNotificationInfo.неизвестный
e.Source = SqlNotificationSource.Тайм-аут
Это может работать в течение недели или более, но вдруг я больше не получаю события изменения и вместо этого получаю событие каждые 60 секунд с
e.Type = SqlNotificationType.+ Изменить
e.Info = SqlNotificationInfo.ошибка
e.Source = SqlNotificationSource.клиент
MSDN документация дляSqlNotificationSource.Client говорит
Произошло инициированное клиентом уведомление, такое как тайм-аут на стороне клиента или в результате попытки добавить команду к уже запущенной зависимости.
Я думаю, это означает, что при создании зависимости произошел тайм-аут.
Один и тот же код работает все время и выглядит так:
private void CreateDependency() {
using (var connection = new SqlConnection(_connectionString)) {
connection.Open();
var command = new SqlCommand();
command.CommandText = "SELECT ...";
command.Connection = connection;
new SqlDependency(command, "ServiceName", DependencyTimeout).OnChange += OnChange;
command.ExecuteNonQuery();
}
}
private void OnChange(object sender, SqlNotificationEventArgs e) {
((SqlDependency)sender).OnChange -= OnChange;
if (e.Type == SqlNotificationType.Change && e.Info == SqlNotificationInfo.Insert) {
_changeWorkerNotifier.Set(); // AutoResetEvent
}
CreateDependency();
}
Если я перезапущу службу, она снова будет работать нормально.
Я провел некоторое расследование и обнаружил, что ошибки появляются после запланированного резервного копирования на сервере (что происходит каждый день). Получил другое приложение, где я в то же время получаю такие ошибки, как
Произошла ошибка транспортного уровня при получении результатов с сервера. (поставщик: поставщик TCP, ошибка: 0 - истек срок ожидания семафора.)
Мое оригинальное предположение было то, чтоSqlDependency.Start()
создает соединение с сервером, которое выходит из строя во время запланированного резервного копирования и никогда не восстанавливается. Но первая строка вMSDN документация говорит
Прослушиватель SqlDependency перезапустится при возникновении ошибки в соединении с SQL Server.
Есть идеи, как это решить?
(Конечно, я могу позволить сервису произойти сбой и заставить его перезапустить диспетчер сервисов. Проблема в том, что сервис также выполняет другие функции, которые необходимо правильно закрыть, поэтому я не могу просто выполнить Enviroment.Exit (-1) из обработчик события)