Question

I am using SQL server tables to act as a queue in my applications. Im using Query Notification using SQL Dependency, notably Jeremiah Gowdy's awesome implementation used in this blog post. http://jgowdy.blogspot.com/2010/01/sqldependency-query-notification-with.html

I implement this in a Windows Service and use it to "listen" to changes on a SQL Table i.e. my queue and do processing on the returned contents of the queue if theres a change - see code below, returns a dataset of the contents of the stored procedure.

The problem is, under heavy load or just over a period of time, changes are no longer detected, even though records exist in the table. When I restart the service the changes are then detected! Ive tried updating the table manually, to trigger a notification but to no avail. It seems like the notification service breaks at some point and fails to re-subscribe, but i cant be sure.

Im desperately trying to find a solution to this problem, as i have to constantly watch for changes in the tables themselves and restart the services if the queue gets stuck - not ideal!

Has anyone else had any issues with SQL Dependency and Query notification? Particularly any guidance on or knowledge on know issues would help. I know better queuing systems exist, but im trying to resolve this problem if i can rather than redevelop the entire project!!!

Here is a code snippet.

//Initialisation
public void StartWatcher()
{
    SqlCommand cmd = new SqlCommand();
    cmd = new SqlCommand("TransferExportQueue");
    cmd.CommandType = System.Data.CommandType.StoredProcedure;

    log.Info("Setting up SQL Watcher");
    //Setup the SQLWatcher
    SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
    builder.ConnectionString = ConfigurationManager.ConnectionStrings["Connexion"].ConnectionString;

    log.Info("Attempting to Start");
    SqlQueueWatcher = new SqlWatcher(builder.ConnectionString, cmd, SqlWatcher.SqlWatcherNotificationType.Blocking);
    SqlQueueWatcher.OnChange += new SqlWatcher.SqlWatcherEventHandler(QueueSQLWatcher_OnChange);
    SqlQueueWatcher.Start();

}

//OnChangeEvent
private void QueueSQLWatcher_OnChange(DataSet Result)
{
    //perform logic in returned contents of stored procedure
}

Here is my stored procedure

Create PROCEDURE [dbo].[TransferExportQueue] 
AS
BEGIN

SELECT [Id]
      ,[TransactionLogId]
      ,[QueueDate]
      ,[UpdateTable]
FROM [dbo].[TransferExportQueue]



END

UPDATE: I have had a sql server logs and im getting the following errors.

The query notification dialog on conversation handle '{9586CB6A-62BA-E311-983B-A0369F0A65D3}.' closed due to the following error: '<?xml version="1.0"?><Error xmlns="http://schemas.microsoft.com/SQL/ServiceBroker/Error"><Code>-8470</Code><Description>Remote service has been dropped.</Description></Error>'.

It seems that Remote service keeps dropping, after more digging, it seems that its got to do with how SQLDependency does its clean up of the subscriptions after every call. Does anyone know how to fix this issue?

Was it helpful?

Solution

Read this article: SqlDependency.OnChange callback timing. The gist of it is that your app has a finite time to process the OnChange callback or the activated procedure timer will kick in and kill the service, wrecking havoc on your app. Personally I'm not a fan of the design, but it is as it is.

Welcome to the club of people who had to abandon the handy SqlDependency usage, with it's just-in-time deployed infrastructure, and use the more basic SqlNotificationRequest class, which requires you to explicitly deploy the target service/queue. What you loose in ease-of-use you'll gain in control over behavior and if you end up dropping the target service from under you're running application at least you'll only have yourself to blame ;)

Seriously though, switching from SqlDependency to SqlNotificationRequest is fairly easy and I recommend it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top