I needed to add caching to my data access routines to improve the performance of commonly accessed data. This is pretty straightforward:
- Check to see if the cache entry already exists
- If the cache entry does exist, return the cached value
- If the cached entry doesn’t exist, fetch the data and add it to the cache.
The problem was, I had a lot of data access routines that I wanted to add caching to. Adding the 4 or 5 lines of code needed to do this to each routine would be tedious, and all of the repetition would be messy. I knew I had to centralize my caching functionality in one place. Since my data access routines returned many different types, I decided to use a generic method to perform the caching. Since the data validation routines essentially had to be wrapped by this function (so that it’s only run if the value doesn’t exist in the cache), I call it using a statement lambda.
//I use ASP.Net's cache object. I get a reference to it with System.Web.HttpRuntime.Cache //as I won't always be using it in the context of ASP.Net private static System.Web.Caching.Cache DataCache = System.Web.HttpRuntime.Cache; public static T CacheFetch<T>(string key, Func<T> fetcher) where T:class { //Don't bother with the caching if the key is null or blank if ((key ?? "").Length <= 0) { return fetcher(); } T result = DataCache[key] as T; if (result == null) { result = fetcher(); if (result == null) { DataCache.Remove(key); } else { DataCache[key] = result; } } return result; }
And here’s some examples of how I used it:
public static IEnumerable<Trustee> GetTrustees(int infoReturnID) { InfoReturnEntities context = new InfoReturnEntities(new Uri(Common.InfoReturnDataServiceURL)); IEnumerable<Trustee> trustees = from trustee in context.Trustees where trustee.InfoReturnID == infoReturnID select trustee; return trustees; }
public static IEnumerable<Trustee> GetTrustees(int infoReturnID) { return Common.CacheFetch<IEnumerable<Trustee>>("Trustees_" + infoReturnID.ToString(), () => { InfoReturnEntities context = new InfoReturnEntities(new Uri(Common.InfoReturnDataServiceURL)); IEnumerable<Trustee> trustees = from trustee in context.Trustees where trustee.InfoReturnID == infoReturnID select trustee; return trustees; }); }
public static IEnumerable<RevenueRange> GetRevenueRanges() { return Common.CacheFetch<IEnumerable<RevenueRange>>("RevenueRanges", () => { InfoReturnEntities context = new InfoReturnEntities(new Uri(Common.InfoReturnDataServiceURL)); IEnumerable<RevenueRange> revenueRanges = from e in context.RevenueRanges where e.RevenueRangeCD != "?" orderby e.LowerLimit select e; return revenueRanges; }); }
My method was inspired by this.
Leave a Reply