Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does any asp.net data cache support background population of cache entries?

We have a data driven ASP.NET website which has been written using the standard pattern for data caching (adapted here from MSDN):

public DataTable GetData()
{
   string key = "DataTable";
   object item = Cache[key] as DataTable;
   if((item == null)
   {
      item = GetDataFromSQL();
      Cache.Insert(key, item, null, DateTime.Now.AddSeconds(300), TimeSpan.Zero;
   }
   return (DataTable)item;
}

The trouble with this is that the call to GetDataFromSQL() is expensive and the use of the site is fairly high. So every five minutes, when the cache drops, the site becomes very 'sticky' while a lot of requests are waiting for the new data to be retrieved.

What we really want to happen is for the old data to remain current while new data is periodically reloaded in the background. (The fact that someone might therefore see data that is six minutes old isn't a big issue - the data isn't that time sensitive). This is something that I can write myself, but it would be useful to know if any alternative caching engines (I know names like Velocity, memcache) support this kind of scenario. Or am I missing some obvious trick with the standard ASP.NET data cache?

like image 470
Yellowfog Avatar asked Aug 01 '10 16:08

Yellowfog


1 Answers

You should be able to use the CacheItemUpdateCallback delegate which is the 6th parameter which is the 4th overload for Insert using ASP.NET Cache:

Cache.Insert(key, value, dependancy, absoluteExpiration,
    slidingExpiration, onUpdateCallback);

The following should work:

Cache.Insert(key, item, null, DateTime.Now.AddSeconds(300),
    Cache.NoSlidingExpiration, itemUpdateCallback);

private void itemUpdateCallback(string key, CacheItemUpdateReason reason,
    out object value, out CacheDependency dependency, out DateTime expiriation,
    out TimeSpan slidingExpiration)
{
    // do your SQL call here and store it in 'value'
    expiriation = DateTime.Now.AddSeconds(300);
    value = FunctionToGetYourData();
}

From MSDN:

When an object expires in the cache, ASP.NET calls the CacheItemUpdateCallback method with the key for the cache item and the reason you might want to update the item. The remaining parameters of this method are out parameters. You supply the new cached item and optional expiration and dependency values to use when refreshing the cached item.

The update callback is not called if the cached item is explicitly removed by using a call to Remove().

If you want the cached item to be removed from the cache, you must return null in the expensiveObject parameter. Otherwise, you return a reference to the new cached data by using the expensiveObject parameter. If you do not specify expiration or dependency values, the item will be removed from the cache only when memory is needed.

If the callback method throws an exception, ASP.NET suppresses the exception and removes the cached value.

I haven't tested this so you might have to tinker with it a bit but it should give you the basic idea of what your trying to accomplish.

like image 75
Kelsey Avatar answered Oct 05 '22 08:10

Kelsey