Почему моя SqlDependency не срабатывает

У меня есть база данных, работающая на MS SQL Server 2005, и веб-приложение ASP.NET 3.5.

База данных содержит каталог продуктов, который я использую для подачи «страниц» в CMS, работающую в веб-приложении. После создания страниц приложение кэширует их, поэтому мне нужно уведомить приложение об этом изменении, чтобы оно могло воссоздать объекты страницы.

CMS использует собственное кэширование, поэтому для выполнения этой задачи нельзя использовать SqlCacheDependency.

Когда я запускаю приложение, я получаю подписчика, появляющегося в результате

select * from sys.dm_qn_subscriptions

Но как только я добавляю какие-то данные в таблицу, подписчик исчезает и событие OnChanged никогда не срабатывает.

В моем коде запуска у меня есть следующее

// Ensure the database is setup for notifications
SqlCacheDependencyAdmin.EnableNotifications(DataHelper.ConnectionString);
SqlCacheDependencyAdmin.EnableTableForNotifications(DataHelper.ConnectionString, "Category");
SqlCacheDependencyAdmin.EnableTableForNotifications(DataHelper.ConnectionString, "Product");

if (!SqlDependency.Start(DataHelper.ConnectionString, SqlDependencyQueueName))
     throw new Exception("Something went wrong");

string queueOptions = string.Format("service = {0}", SqlDependencyQueueName);
using (var connection = new SqlConnection(DataHelper.ConnectionString))
{
     connection.Open();
     using (SqlCommand command = new SqlCommand(@"SELECT [CategoryID],[Name]
                   FROM [dbo].[Category]", connection))
     {
           // Create a dependency and associate it with the SqlCommand.
           dependency = new SqlDependency(command, queueOptions, 0);

            // Subscribe to the SqlDependency event.
            dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);

            command.ExecuteReader().Close();
        }
    }

// ...

void OnDependencyChange(object sender, SqlNotificationEventArgs e)
{
    Debugger.Break(); // This never hits
    this.ReloadData();
}

person Greg B    schedule 23.08.2010    source источник
comment
кстати, вы всегда должны проверять члены SqlNotificationEventArg перед перезагрузкой данных. В противном случае вы рискуете создать замкнутый цикл, который перезагружается при каждом некорректном операторе или уведомлении о неверных настройках. И лучше просто сделать кеш недействительным и позволить следующему доступу загрузить данные, а не упреждающую перезагрузку при уведомлении (по тем же причинам, чтобы избежать плохой ситуации, когда он сильно зацикливается).   -  person Remus Rusanu    schedule 23.08.2010


Ответы (2)


Проверьте свою базу данных sys.transmission_queue. Скорее всего, ваши уведомления будут сохранены, потому что они не могут быть доставлены. У transmission_status будет объяснение, почему это происходит. Более подробное руководство по устранению неполадок см. в разделе Диалоговые окна устранения неполадок.

Наиболее частая проблема возникает из-за того, что требования к инфраструктуре EXECUTE AS не удовлетворяются владением dbo потерянной базы данных и может быть решена с помощью:

ALTER AUTHORIZATION ON DATABASE::<dbname> TO [sa];

однако решение зависит от случая к случаю, в зависимости от реальной проблемы, как исследовано выше.

person Remus Rusanu    schedule 23.08.2010

Ваш выбор неверен. Вы должны явно указать Query. Из документов Microsoft SQL:

Спроецированные столбцы в операторе SELECT должны быть указаны явно, а имена таблиц должны быть дополнены именами, состоящими из двух частей. Обратите внимание, что это означает, что все таблицы, на которые ссылается оператор, должны находиться в одной и той же базе данных.

person Paul.Schwan    schedule 16.07.2020