3

I'm trying to make use of SqlDependancy in a SignalR project, but I can't seem to get the OnChanged event to fire more than once. It fires initially on the subscribe event, but it never fires again after making changes to the underlying database. I've omitted my SignalR and controller code because the problem seems to lie in the repository class. SqlDependancy.Start() is declared in my Global.asax class.

Watching from the SQL server, I can see a notification queue is created when my application starts, and is terminated when I close as well.

    public IEnumerable<Visitor> NotifyAllClients()
    {
        List<Visitor> visitors = new List<Visitor>();
        using (var connection = new SqlConnection(new VisitorLogEntities().Database.Connection.ConnectionString))
        {
            using (var command = new SqlCommand(@"SELECT * FROM dbo.Visitors", connection))
          //using (var command = new SqlCommand(@"SELECT [Id],[AgreeToTerms],[Base64Image],[CheckInDate],[CheckOutTime],[Company],[CountryOfOrigin],[email],[FirstName],[LastName],[IsInBuilding],[MeetingSubject],[MeetingTime],[PatriotHost],[phone],[title] FROM dbo.Visitors", connection))
            {

                var dependency = new SqlDependency(command);
                dependency.OnChange += Database_OnChange;

                if (connection.State == System.Data.ConnectionState.Closed)
                    connection.Open();

                var reader = command.ExecuteReader();

                while (reader.Read())
                {
                 ////compile visitor objects
                 ////visitors.add(new Visitor());
                }
            }
            return visitors.OrderByDescending(x => x.CheckInDate);
        }
    }

    private void Database_OnChange(object sender, SqlNotificationEventArgs e)
    {
        //var dependency = (SqlDependency)sender;
        //dependency.OnChange -= Database_OnChange;

        ////this fires once, with the Type of 'Subscribe', but then never fires on CRUD changes
        if (e.Type == SqlNotificationType.Change)
        {
            VisitorHub.SendVisitors();
        }
        //NotifyAllClients();
    }

edit: lines of code commented out above indicate the changes needed to get this working correctly.

Lee Harrison
  • 2,306
  • 21
  • 32
  • 1
    I believe you need to re-subscribe after every notification. http://stackoverflow.com/questions/15566966/sqldependency-onchange-not-firing – Dave Dec 03 '15 at 20:23
  • I understand that, but if I re-subscribe it simply fires the OnChanged handler again with a 'Subscribe' type. Which part of the code exactly is the resubscription? I assume it is the command.ExecuteReader() method, but once that fires the subscription is over. Where would this re-subscription take place? – Lee Harrison Dec 03 '15 at 20:33
  • Check this example from msdn https://msdn.microsoft.com/en-US/library/a52dhwx7(v=vs.80).aspx paying particular attention to step 12 and 13 in the watcher application. In step 12 you will see the removal of the onChange event and then it calls step 13 which sets it up again. – Dave Dec 03 '15 at 20:45
  • So basically when stepping through the debugging it just loops setting up the dependency, hitting the on changed handler with a subscribe event, then tearing it back down. Over and over again. At least that's the behavior I'm seeing. – Lee Harrison Dec 03 '15 at 21:05
  • 2
    I think you are seeing bad behavior due to your sql statement itself. The sql statement has to follow some rules. See https://msdn.microsoft.com/en-US/library/aewzkxxh(v=vs.80).aspx for more info. In particular the Writing Notification Queries section. "The statement may not use the asterisk (\*) or table_name.\* syntax to specify columns." – Dave Dec 03 '15 at 21:11
  • You're an epic hero Dave, the asterisk was the final piece of the puzzle. Its all working correctly now. If you can wrap you comments up in to an answer I'll mark it as correct. Thanks a million! – Lee Harrison Dec 03 '15 at 21:17
  • Glad to have helped. Getting these to work is complicated and I have been foiled by the asterisk as well. Getting those SQL statements to work based upon teh restrictions is key. – Dave Dec 03 '15 at 21:22

1 Answers1

7

Check this example from msdn http://msdn.microsoft.com/en-US/library/a52dhwx7(v=vs.80).aspx. Download the VS2005_General_en-us.pdf. Page 24636, "Using SqlDependency in a Windows Application" is the section the original link led to. Pay particular attention to step 12 and 13 in the watcher application. In step 12 you will see the removal of the onChange event and then it calls step 13 which sets it up again.

Also, I think you are seeing bad behavior due to your sql statement itself. The sql statement has to follow some rules. See https://technet.microsoft.com/en-us/library/ms181122(v=sql.105).aspx for more info. In particular the Writing Notification Queries section. "The statement may not use the asterisk (*) or table_name.* syntax to specify columns."

Dave
  • 498
  • 2
  • 12
  • Both links are broken, can you update them? I'm having same issue! – DiegoS Nov 23 '17 at 15:23
  • I have updated the answer. The first link leads to a document you must download to see what I was referring to. I updated the second link to a working link. – Dave Nov 27 '17 at 18:31
  • I was using the asterisk(*) but after removing it, it now sees the on Change event. Thanks – Fortune Jan 22 '18 at 10:40