Geeks With Blogs

Michael Freidgeim's Blog MS .Net Development
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 on Thursday, October 4, 2007 9:13 PM | Back to top


Comments on this post: Generic LoadFromCache method to reliably read data from cache.

# re: Generic LoadFromCache method to reliably read data from cache.
Requesting 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?
Left by Liviu on Oct 07, 2007 9:23 PM

# //TODO how to declare delegate that returns generic type
Requesting Gravatar...
public delegate T CreateInstanceDelegate<T>();
Left by anon on Nov 09, 2008 3:33 PM

Your comment:
 (will show your gravatar)


Copyright © Michael Freidgeim | Powered by: GeeksWithBlogs.net | Join free