Advanced ASP.NET caching events

Edit on GitHub

Currently, I'm giving an ASP.NET classroom training at our company, which actually is quite good for me: I needed to refresh all ASP.NET concepts, as those all fade away slowly when you don't use them for a while... Now, one of those refreshed concepts is ASP.NET's caching.

ASP.NET offers a flexible built-in caching mechanism, providing you with a global "Cache" object in which you can get and put data which needs to be cached for a while. One of the cool things about ASP.NET caching is that it actually listens to what you want: if you need the cache to expire after 10 minutes, it does so. Also, when memory is needed for other actions on the webserver, ASP.NET will gently clean the cache depeding on cache item priorities.

As for many things in this world, every good thing also has a downside... And here's the downside for ASP.NET's caching: when an item is removed from cache, you'll have to know and react to that. No problem, you say, as you can simply use an if-statement to fix things up. Here's a DataDet which will be cached to infinity (or untill memory is needed):

[code:c#]

if (Cache.Get("myDataSet") == null) {
    // Re-fetch data
    // ... DataSet ds = ....

    Cache.Insert(
        "myDataSet", ds, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration
    );
}

[/code]

Great thing! But... What if I want to centralise cache creation? What if I want to log something everytime a cache item has been removed due to memory limits being reached? Luckily, ASP.NET provides an answer to that: the System.Web.Caching.CacheItemRemovedCallback delegate. This delegate can be used to ask ASP.NET to notigy you using a delegate of what is happening inside the cache when something is removed from it. Here's the delegate signature:

[code:c#]

void (string key, Object value, CacheItemRemovedReason reason);

[/code]

As you can see, you can get the key that's being removed, its current value, and the reason why the item is being deleted. These reasons can be: Expired, Removed, Underused, and DependencyChanged. I think these speak for themselves, no?

Now let's implement this: I'll create a CacheRetrievalManager which will update my cache whenever an item is removed from cache:

[code:c#]

using System;
using System.Web.Caching;

public class CacheRetrievalManager
{
    public void RemovedCacheItemHandler(string key, Object value, CacheItemRemovedReason reason)
    {
        switch (key)
        {
            case "myDataSet":
                // call method to re-fetch data and re-set cache
                // ...
                break;
        }
    }
}

[/code]

One thing left is to specify that this method should be called whenever a cache item is removed:

[code:c#]

// Insert in cache ONCE, recreation will be handled by CacheRetrievalManager
DataSet ds = ...;
Cache.Insert(
    "myDataSet", ds, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheRetrievalManager.RemoveCacheItemHandler
);

[/code]

Now I know exactly why something is removed, and that I can even log when this happens. You can now further extend this into separate CacheRetrievalManagers for every object you which to cache, fetch data inside that manager, ...

This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.

Leave a Comment

avatar

2 responses

  1. Avatar for Paul Jones
    Paul Jones October 24th, 2008

    Hi Maarten!

    Just wanted to point out that there are quite a few number of drawbacks associated with asp.net cache. Its not scalable and cache synchronization is a pain in the neck. If you want to share various bottlenecks with your students, please visit aspnetcache.wordpress.com

    Cheers,

    Paul.

  2. Avatar for Sarah Williams
    Sarah Williams November 26th, 2008

    I agree with Paul. ASP.NET Caching mechanism isn't scalable due to its in-process standalone nature. That's why Microsoft has entered the distributed caching arena themselves. Distributed caching not only improves performance, but also keeps cache synchronized across multiple servers.

    All the best!