views:

240

answers:

2

I have put together a small ASP.NET MVC 2 site that does some very extensive date mining/table-joins/etc.

Using MVC, I have a controller that returns the data in many different forms (tables, images, etc). To save hitting the database frequently I have a dual cache mechanism:

  1. For identical parameters to the same action I use the OutputCacheAttribute with VaryByParam = "*".
  2. Assuming some parameter to the action has changed (or another action is called), it is still possible that my "data" has previously been requested, so I store the data in a view model after the first hit of the database, I achieve this with a .NET 4.0 System.Runtime.Caching.ObjectCache.

Example of the ObjectCache inside of the Controller:

private static readonly ObjectCache cache = 
      new MemoryCache("CompareControllerCache");
private static void CacheObject(ViewModel obj, 
                                string param1, 
                                int someOtherParam )
{
    string key = string.Format("{0}-{1}", param1, someOtherParam);
    Trace.WriteLine(string.Format("Adding {0} to the cache", key));
    cache.Add(key, obj, new CacheItemPolicy
         {
             SlidingExpiration = TimeSpan.FromMinutes(1)
         });
}

// Corresponding GetCachedObject with similar key defining logic.

This gives me a good performance improvement, but where it fails is on the CacheItemPolicy being very simple. Ideally, I'd like the cache-window to be bigger but have the cached item expire if the database changes.

The CacheItemPolicy seems to support this with the ChangeMonitors collection, to which I could add a SqlChangeMonitor, but when trying to construct this is where I come to a halt.

I am using Entity Framework 4 to access an SQL Database, how how do I construct the SqlChangeMonitor to monitor the couple of database tables that are likely to trigger a cache expire?

SqlChangeMonitor is constructed with an SqlDependency which takes an SqlCommand - how can I latch upon Entity Framework's encapsulation of my database?

+3  A: 

It is possible to wrap any arbitrary LINQ query in a SqlDependency, including EF Linq queries, see LinqToCache. But unfortunately the way EF chooses to formulate the SQL for the queries, even the most simple from t in context.table select t, is incompatible with the Query Notificaiton restriction and the SqlDependency is invalidated straight away as an invalid statement. I have talked about this in SqlDependency based caching of LINQ Queries.

What you can do is use SqlChangeMonitor with straightforward SqlCommand objects constructed as simple SELECT ... FROM Table on your tables that are likely to change. You need to understand that there is a balance between the cost of setting up notifications and the cost of polling, if your tables change frequently then monitoring for changes could turn out to be more expensive than polling. See this article The Mysterious Notification to understand how QN works and what is the cost of monitoring.

Remus Rusanu
In this specific case, the data changes very infrequently (10-20 records updated per week), but this is a learning project and I'd like to understand how to "do the right thing" in a heavier changing environment - will follow your links. Thanks.
Ray Hayes
Caching the 'data-retrieval' is key, it takes ~3 seconds to process the thousands of records I have - although I could spend some time optimising, it still will not be quick - whereas because of the slow-rate of change, caching the data will seldom be expired!
Ray Hayes
A: 

hi answer with implementation can be found at below site

http://harismile.wordpress.com/2010/09/09/mvc-with-ef-sqldependencycache/

hari