SqlDependency в службе Windows не запускается

Я пытаюсь отслеживать таблицу базы данных на предмет изменений, используя класс SqlDependency. Хотя я должен что-то упустить. Я следил за всеми примерами, которые я вижу в Интернете, и я рассмотрел все вопросы на этом сайте. Я просто не вижу, чего мне не хватает. Вот начальные команды, которые я выполнил в базе данных, чтобы включить компонент Service Broker и создать очередь и службу.

CREATE QUEUE ScheduleChangeQueue
GO

CREATE SERVICE ScheduleChangeService ON QUEUE ScheduleChangeQueue ([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
GO

ALTER DATABASE [database] SET ENABLE_BROKER

На стороне C# я создал класс с единственным статическим методом установки, который вызывается для запуска процесса. Вот код для этого:

public class SqlDependencyManager
{
    private static bool DoesUserHavePermission()
    {
        var success = false;
        try
        {
            Program.Log.Info("Retrieving SqlPermission to establish dependency...");

            var clientPermission = new SqlClientPermission(System.Security.Permissions.PermissionState.Unrestricted);

            // this will throw an error if the user does not have the permissions  
            clientPermission.Demand();

            success = true;

            Program.Log.Info("SqlPermission established. Continue setting up dependency.");
        }
        catch (Exception ex)
        {
            Program.Log.Error(ex, "SqlPermission not able to be established.");
        }

        return success;
    }

    public static void Setup()
    {
        if (!DoesUserHavePermission())
        {
            return;
        }

        var connectionString = ConfigurationManager.ConnectionStrings["ShowMakerPro"].ConnectionString;

        // You must stop the dependency before starting a new one. 
        // You must start the dependency when creating a new one. 
        SqlDependency.Stop(connectionString);
        SqlDependency.Start(connectionString);

        using (var cn = new SqlConnection(connectionString))
        {
            using (var cmd = cn.CreateCommand())
            {
                cmd.CommandType = CommandType.Text;
                //cmd.CommandText = "SELECT MAX(LastChangeTime) FROM Schedule WHERE ChannelID IN ( SELECT ID FROM Channels WHERE Type = 1 ) AND StartTime BETWEEN (GETDATE() - 7) AND (GETDATE() + 30)";
                cmd.CommandText = "SELECT LastChangeTime FROM dbo.Schedule";
                cmd.Notification = null;

                // Creates a new dependency for the SqlCommand. Then creates attaches handler for the notification of data changes
                new SqlDependency(cmd).OnChange += SqlDependency_OnChange;

                cn.Open();

                cmd.ExecuteReader();
            }
        }

        Program.Log.Info("SQL Dependency set. Now monitoring schedule table for changes.");
    }

    private static void SqlDependency_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change)
        {
            // this will remove the event handler since the dependency is only for a single notification
            ((SqlDependency)sender).OnChange -= SqlDependency_OnChange;

            ScheduleOutputterService.BuildSchedules();

            Program.Log.Info("SQL Dependency triggered schedule rebuild. Resetting SqlDependency to monitor for changes.");

            Setup();
        }
    }
}

Я вижу, что код настроен нормально, и метод OnChange запускается один раз для подписки, но после этого я никогда не вижу его запуска. Я вручную захожу в базу данных и изменяю поле LastChangeTime, надеясь, что оно вызовет событие, но ничего не происходит.

Может кто-нибудь, пожалуйста, пролить свет на то, где я облажался? Я вижу, что некоторые люди говорят онлайн, что это прекрасно работает в форме окон, но у них также есть некоторые проблемы во время службы.

1 ответ

Решение

Итак, я наконец-то нашел ответ на свой вопрос и подумал, что мне следует перечислить все шаги, которые я предпринял, чтобы добраться до этой точки, чтобы у кого-то другого, идущего позади меня, также было другое место для поиска ответов, так как я, казалось, не мог найти все мои ответы в одном месте.

Во-первых, я заметил, что как только подписка была установлена, OnChange событие начнется сразу. Вот почему я включил проверку типа изменения, чтобы я мог игнорировать эти события. Оказывается, игнорировать эти события было нехорошо, потому что эти события на самом деле пытались мне что-то сказать. Поиск моих ценностей направил меня сюда:

http://msmvps.com/blogs/siva/archive/2011/11/22/subtle-sqldependency-notification-issue.aspx

Это было очень ценно, потому что помогло мне увидеть, что, возможно, были проблемы с некоторыми из моих опций в базе данных. При дальнейшей проверке я заметил, что моя база данных настроена на совместимость с SQL Server 2000. Это, очевидно, моя первая проблема, потому что это особенность 2005 года и выше. Поэтому я попытался изменить свои настройки на старшую версию. Это работало хорошо, но потом я все же заметил, что получаю то же событие. Затем я проверил настройки своей базы данных и обнаружил, что они не настроены так, чтобы соответствовать параметрам, необходимым для запуска компонента ServiceBroker. Вы можете увидеть все необходимые параметры настройки здесь:

http://msdn.microsoft.com/en-us/library/ms181122(v=SQL.100).aspx

После того, как я проверил все это и попытался сделать некоторые обходные пути, чтобы получить правильные настройки, все в квадрате, установка все еще терпела неудачу. Но на этот раз это не удалось, потому что обновления не сохранятся. Оказалось, что у клиента были триггеры в рассматриваемой таблице, и его настройки базы данных, которые использовались для выполнения триггера, конфликтовали с необходимыми настройками для запуска QueryNotifications.

Короче говоря, клиент решил, что он не хочет менять все используемые триггеры, поэтому они отказались от усилий. Но я многое узнал о том, как устранять неполадки SqlDependency и ServiceBroker. Надеюсь, что эти несколько ссылок, которые я предоставил, будут полезны для кого-то еще. Еще пара ссылок, которые были очень полезны, были упомянуты в комментариях, но я собираюсь опубликовать их в этом ответе, чтобы вы могли рассмотреть некоторые другие пункты.

http://rusanu.com/2006/06/17/the-mysterious-notification/

http://rusanu.com/2005/12/20/troubleshooting-dialogs/

Другие вопросы по тегам