I have been using this code for a while now and thought I would post it out to the community as a simple C# DataCache class that can be re-used.

This is only really applicable to non-web farm solutions as the data will be stored in process per IIS instance. If you want a distributed solution then look to pay big(ger) bucks or if you are hosting your site in Windows Azure thenAppFabric Caching is the go and very reasonably priced.

With that disclaimer aside though this works nicely for any single server solution and will cache any type of data.

I chose to have a DataCacheItem enum for each project I use this on, which is one of the parameters to the Insert, Get, Contains and Remove methods but you could always change to a string if you like. I prefer the strongly typed approach as it saves on typing errors.

Code below the break

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Runtime.Caching; namespace BondiGeek.Code { publicenum DataCacheItem { LastTweet, WeatherReport, Toolbox, Work, Home, Blog } ///

/// Library used for arbitrary caching of objects/// publicclass DataCache { publicstaticvoid Insert(DataCacheItem key, T value) { lock (MemoryCache.Default) { MemoryCache.Default.Remove(key.ToString()); DateTimeOffset expires = new DateTimeOffset(DateTime.Now.AddMinutes(Properties.Settings.Default.CacheDurationInMinutes)); MemoryCache.Default.Add(key.ToString(), value, expires); } } publicstaticvoid Insert(DataCacheItem key, int subKey, T value) { lock (MemoryCache.Default) { MemoryCache.Default.Remove(string.Format("{0}-{1}", key.ToString(), subKey)); DateTimeOffset expires = new DateTimeOffset(DateTime.Now.AddMinutes(Properties.Settings.Default.CacheDurationInMinutes)); MemoryCache.Default.Add(string.Format("{0}-{1}", key.ToString(), subKey), value, expires); } } publicstatic T Get(DataCacheItem key) { if (MemoryCache.Default.Contains(key.ToString())) { return (T)MemoryCache.Default.Get(key.ToString()); } else { returndefault(T); } } publicstatic T Get(DataCacheItem key, int subKey) { if (MemoryCache.Default.Contains(string.Format("{0}-{1}", key.ToString(), subKey))) { return (T)MemoryCache.Default.Get(string.Format("{0}-{1}", key.ToString(), subKey)); } else { returndefault(T); } } publicstaticbool Contains(DataCacheItem key) { return MemoryCache.Default.Contains(key.ToString()); } publicstaticbool Contains(DataCacheItem key, int subKey) { return MemoryCache.Default.Contains(string.Format("{0}-{1}", key.ToString(), subKey)); } publicstaticvoid Remove(DataCacheItem key) { MemoryCache.Default.Remove(key.ToString()); } publicstaticvoid Remove(DataCacheItem key, int subKey) { MemoryCache.Default.Remove(string.Format("{0}-{1}", key.ToString(), subKey)); } } }

Usage is pretty darn simple and there is one overload for each method which takes a subKey of type int. This is a bit of a throw back from the first project I used it on but subKey always seems to be an ‘int’ for me so I have just left it as is. Again, feel free to change this to a more generic type if you want to improve the code.

Below is some sample code of how to use the class. In this case I have a Home Controller which returns a Home Model. The model data rarely changes so is cached for a period of time and returned from the cache when available, which in my case will be for 15 minutes. The LoadHomeModel() method is a helper function which does all the hard work of loading the model.

public ActionResult Index() { // Get the data from the cache if availableif (!DataCache.Contains(DataCacheItem.Home)) { DataCache.Insert(DataCacheItem.Home, LoadHomeModel()); } return View(DataCache.Get(DataCacheItem.Home)); }

Hope you find the code useful and if you have any ideas for improvement, aside from making the key and subKey more generic, please drop me a line.

If you spot any problems with this implementation I would also love to hear from you.