We are working on a large legacy application and we're redesigning the business layer and the data layer. We believe that it is a good time to redesign the way cache is handled. Are there any patterns and best practices for implementing a caching layer (or building it in the business layer)?
The only things that I can think of are to use SQL Cache Dependency (which is hard because of we've got a big legacy database with a lot of tables that do not always correspond to the business objects) and implementing strongly typed CacheManager class to hide the string keys and eliminate class casting problems.
Is there anything more sophisticated that we can do? Is there any way to enforce cache invalidation when performing update/delete? Should we somehow maintain a single object in the cache and retrieve list of IDs from the DB that always work with the same objects?
Basically what techniques for caching do you use in ASP.NET? Too bad we cannot use IoC containers or ORM frameworks that support cache :(
Edit: I am more concerned about maintainability than performance.
public T GetFromCache<T>(string key, Func<T> ifKeyNotFoundDelegate)
to ensure that cache is always used the same. [1]Ah well, that covers most of what we do in our website (20GB memcached cluster spread over 20 servers).
[1] By making such a function the only interface to store stuff in cache, you can achieve the following. Let's say I want to use something from the cache, like the result from a function. Normally you would do something like
CacheManager cm = new CacheManager(CacheGroups.Totals);
object obj = cm.GetFromCache("function1result");
if(obj == null)
{
obj = (object)DAO.Foo();
cm.StoreInCache("function1result", obj);
}
return (List<MyEntity>)obj;
By using a different interface you can ensure that users won't make a mistake here.
Like
public T GetFromCache<T>(string key, Func<T> ifnotfound)
{
T obj = this.GetFromCache(key) as T;
if(obj == default(T))
{
obj = ifnotfound.Invoke();
this.StoreInCache(key, obj);
}
return obj;
}
This ensures that
Ergo: less probable that they make a mistake. Furthermore: you get nicer, more clear, code, like:
List<MyEntity> list = new CacheManager(CacheGroups.Total).GetFromCache<List<MyEntity>>("function1result", ()=>DAO.Foo());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With