Generic LoadFromCache method to reliably read data from cache.

The typical procedure to work with cache is
1.to check if item for specified key exist in a cache;
2.if yes, return it;
3.if no, create it (e.g load from database),
4.save to the cache
5. and then return it.
Some developers use the code like the following
:

If (DataCache.GetCache["key"] == null)
{   // code for loading object
   ...
   
DataCache.SetCache("key", obj);
}
return DataCache.GetCache["key"]; //Not good, can cause problems (at least in ASP.Net 2.0).
Sometimes SetCache is not effected immediately(or expired immediately) and subsequent GetCache returns null.

Back in 2006 I lost a lot of time trying to debug the problem in DotNetNuke "DataCache.GetCache usage pattern causes random Null reference exceptions".
Now in a different application I noticed the same unreliable pattern.

To avoid mistakes and make process of getting objects from cache consistent, I've created a Generic function with delegate as a parameter  to implement the safe pattern.

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
 
    public static class CacheHelper
    {
        
public delegate T CreateInstanceDelegate<T>();
        public  static T  LoadFromCache<T>(String cacheKey, CreateInstanceDelegate<T> dlgt) where T:class 
        {
            T coll = HttpRuntime.Cache[cacheKey] as T;
            if (coll == null)
            {
                coll = dlgt() as T;
                if (coll != null)
                {
                    HttpRuntime.Cache[cacheKey] = coll;
                }
            }
            return coll;
        }
       public static string GetFileFromHttpServerToCache(String url,bool throwIfNotFound) 
        {
            //TODO: alternatively  add file dependancy
            //System.Web.HttpContext.Current.Cache.Add(cacheKey, contents, new CacheDependency(fileName), DateTime.MaxValue, TimeSpan.FromHours(2), CacheItemPriority.Normal, null);
            String content = CacheHelper.LoadFromCache<String>(url, delegate
            {
              string filePath=  HttpContext.Current.Server.MapPath(url);
              if (throwIfNotFound == false && !File.Exists(filePath))
              {
                  return "";
              }
              string sContent = StreamHelper.FileToString(filePath);
              return sContent;
            });
            return content;
        }
       public static string GetFileFromHttpServerToCache(String url,bool throwIfNotFound) 
        {
            //TODO: alternatively  add file dependancy
            //System.Web.HttpContext.Current.Cace.Add(cacheKey, contents, new CacheDependency(fileName), DateTime.MaxValue, TimeSpan.FromHours(2), CacheItemPriority.Normal, null);
            String content = CacheHelper.LoadFromCache<String>(url, delegate
            {
              string filePath=  HttpContext.Current.Server.MapPath(url);
              if (throwIfNotFound == false && !File.Exists(filePath))
              {
                  return "";
              }
              string sContent = StreamHelper.FileToString(filePath);
              return sContent;
            });
            return content;
        }
}
Example of call, utilizing C# anonymous delegates(available starting from .Net 2.0) :
           MyClass entity =
                CacheHelper.LoadFromCache<MyClass >(sCacheKey, delegate
                {
                    return LoadFromDb(localParameters);
                });
Another article describing similar approach is The 'Reluctant Cache' Pattern
Related(sort of) links: New feature about Generics in .Net 3.5
posted @ Thursday, October 4, 2007 9:13 PM
Print

Comments on this entry:

# re: Generic LoadFromCache method to reliably read data from cache.

Left by Liviu at 10/7/2007 9:23 PM
Gravatar
It is sooo evident that noonw has to use:
return DataCache.GetCache["object"];...

It is like reading the object back from the database after you save it, instead of returning the already availabe object...

Man, does anybody have some common sense these days?

# //TODO how to declare delegate that returns generic type

Left by anon at 11/9/2008 3:33 PM
Gravatar
public delegate T CreateInstanceDelegate<T>();

Your comment:



(not displayed)

 
 
 
 
 

Live Comment Preview:

 
«April»
SunMonTueWedThuFriSat
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910