Using C# delegates with ASP.NET data caching

When using the data cache in ASP.NET, the standard practice is to: 

  1. Check if the object exists in the data cache
  2. If not, then create/generate object and store the new object in the cache for the next time
  3. Return the object

 In an effort to condense this code,  I’ve come up with the following CacheManager base class:

public abstract class CacheManager : ICacheManager
    {

        public CacheManager()
        {
            TimeoutMinutes = 60;
            AbsoluteExpiration = System.Web.Caching.Cache.NoAbsoluteExpiration;
            Dependency = null;
            ItemPriority = CacheItemPriority.Default;
            ItemRemovedCallback = null;
        }

        public double TimeoutMinutes { get; set; }
        public DateTime AbsoluteExpiration { get; set; }
        public CacheDependency Dependency { get; set; }
        public CacheItemPriority ItemPriority { get; set; }
        public CacheItemRemovedCallback ItemRemovedCallback { get; set; }

        protected virtual string KeyPrefix
        {
            get
            {
                return string.Empty;
            }
        }

        private string FullKey(string key)
        {
            if (!string.IsNullOrEmpty(this.KeyPrefix))
                return this.KeyPrefix + "." + key;
            else
                return key;
        }

        public void Add(object cacheObject, string key)
        {
            this.Add(cacheObject, key, this.TimeoutMinutes);
        }
        private void Add(object cacheObject, string key, double minutes)
        {
            HttpContext.Current.Cache.Insert(FullKey(key), cacheObject,
                                    this.Dependency,
                                    this.AbsoluteExpiration,
                                    TimeSpan.FromMinutes(minutes),
                                    this.ItemPriority,
                                    this.ItemRemovedCallback);
        }

        public void Remove(string key)
        {
            HttpContext.Current.Cache.Remove(FullKey(key));
        }

        public bool Exist(string key)
        {
            return HttpContext.Current.Cache[FullKey(key)] != null;
        }

        public virtual T Get<T>(string key) where T : class
        {
            return HttpContext.Current.Cache[FullKey(key)] as T;
        }

        public virtual T Get<T>(string key, Func<T> fn) where T : class
        {
            return this.Get<T>(key, this.TimeoutMinutes, fn);
        }
        public virtual T Get<T>(string key, double timeoutminutes, Func<T> fn) where T : class
        {
            var obj = this.Get<T>(key);
            if (obj == default(T))
            {
                        obj = fn();
                        this.Add(obj, key, timeoutminutes);
            }

            return obj;
        }
    }

The key methods to notice are the “Get” methods. They allow passing in an anonymous delegate so that steps 1 through 3 from above are condensed into a single method call. The following code would retrieve the “book” object from the data cache or the data access layer and return it:


var book = ServiceDataCache.Get("GetBook." + authorName, 60, delegate()
{
    return DataAccess.GetBook(authorName);

});

Advertisements

About Paul Martin

I enjoy rock climbing, playing guitar, writing code...
This entry was posted in .NET, C#, cache. Bookmark the permalink.

4 Responses to Using C# delegates with ASP.NET data caching

  1. Pingback: Attribute driven caching in ASP.NET (using Ninject) | My brain's page file

  2. Thank you Paul!

    I’m facing exactly this scenario, but I’m unable to reuse your code, as the library that takes care of caching is used on different tiers of my solution (including business classes), that doesn’t and can’t reference System.Web.
    therefore HttpContext.Current.Cache is not an option.

    I was considering to use something like “ObjectCache cache = MemoryCache.Default;” as a cache repository, and transform your class in a static class (so to keep using it in the same way as you do), but I can’t see how can I do that.

  3. I’ve forgotten to check the “Notify my…” checkbox, so I had to write a new useless comment 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s