7

I have been doing some research and I can see most of the plumbing for this system however I'm not sure how sql server knows when to fire a message back to any listeners (applications) when data in a table changes, for instance. I'll start by explaining what I understand up to the point that I'm getting lost.

1) Service Broker needs to be enabled on the database and some permissions need to be set.

2) The database schema should be deployed.

3) Using aspnet_regsql.exe, enable sql cache dependency for the database and tables you need to cache data for (this step creates a table to track changes and triggers on the tables to capture changes and increment a value in that table).

4) Set up the sql cache dependency in the .net application. For instance, in a web app, you'll need to add config values for the poll time, connection string, etc; start/stop the dependency in your global.asax.cs, and then add sql cache dependencies when you add items to your cache.

4a) Part of what happens when starting the dependency is that the infrastructure is set up for a queue, a service, and a sproc for communication and cleanup afterwards. Using Sql Query Profiler, you can see connection being made and a communication channel being set up on the service for the application to receive messages from sql server.

5) Here is where I get confused. At this point, I've cached an item in my application cache with a reference to the sql cache dependency on the underlying table so that my app can receive changes in case that row changes. If I manually run an update on that row, I can see the trigger being hit and the value in the tracking table being incremented by 1. However, I do not see any communication going back to the application, nothing on sql query profiler, nor is the item removed from the cache. I also don't see anything in the queues on the database (neither the dynamic application queue nor the standard error/transmission queues)

My question is, what is watching that tracking table in the database so that messages can be sent back up to the sql dependencies that are concerned about changes to this data?

Any help is greatly appreciated... I've been scouring through many online references and can't find any concrete explanation of this.

longda
  • 10,153
  • 7
  • 46
  • 66

1 Answers1

5

A new table is created in your database that holds a name of the table you want to check for updates on, and a change number. Each table you have setup for sqldependency has a trigger set up for updates/inserts that increments the changeid in the new table I just described.

Your mental model of how this works is backwards. Your application checks the log to determine if a table has changed.

So if the changelog table (That's what I call it) is tracking two tables in your database (Product, User) It will look like this.

+Table Name + ChangeNumber +
| Product   | 1            |
+-----------+--------------+
| User      | 1            |
+-----------+--------------+

Now if you modify anything in either of these tables, the trigger will increment ChangeNumber and we now know they changed.

Obviously there is more to this, but this is the general idea.

Note: It should be noted that you can invalidate a page if one or more tables change, so if your page has dependency set up for both of these tables, if one of them changes it will invalidate the cached page and re-cache an updated version.

The Muffin Man
  • 19,585
  • 30
  • 119
  • 191
  • 1
    Ok, I think I get it. So when the app starts up, it would check, in your example, the current changeId for Product is 1 and User is 1. So that's the baseline. Then based on the poll time set in the config file, it will hit the db to check if that changeId has gone up. If so, it will keep the new value for the next check and dump the item from cache. Another flaw I've just realized is that if I'm caching Users and any of those users change, all of them get dumped from the cache. Wasn't planning on that but it makes sense as to how the dependencies are designed to work. – longda Sep 08 '11 at 21:00
  • 1
    I don't think the app polls, if you request a page that has Product as one of the sql dependencies it will hit the db first to see if Product changed in the changelog table. If not, send back cached page, if so, invalidate page. I'm not sure what you mean by all the users are dumped from the cache. If you have a page that displays a list of users and some details, set the sqldependency to User, the page will be cached until something in the User table changes. Your not caching the table in memory, your caching all of the associated data on some page so it doesn't have to requery. – The Muffin Man Sep 09 '11 at 00:10
  • @longda, if you're still having trouble with this or need more help just let me know. – The Muffin Man Sep 09 '11 at 06:35
  • 1
    Thanks @Nick for your help! I identified a problem I was having in my application (using MVC3 + MVC-Mini-Profiler + Nhibernate + SysCache2). Turns out, some of the code I was using to profile the db connections with NHibernate was broken, I believe due to the calls being made from the app to db for polling was using batching(?). At any rate, I switched back to the standard NHibernate SQL Driver and POOF! the sql dependencies started working. Along the way, once I saw everything working, I realized it wasn't the right solution because one row change in a table will dump that cache region. – longda Sep 09 '11 at 20:11
  • 2
    So, sql dependencies had the plug pulled on them and I'll be investigating distributed, out-of-process caches like Memcache and App Fabric/Velocity/Whatever it's being called today. Cheers! – longda Sep 09 '11 at 20:12