September 27, 2014

Expiration Of Cache Values For Dependent Objects

One of the most important features of the medium to large scale applications is caching system, especially if you are implementing Data Driven applications. In this blog I am going to discuss about caching on data and offer a solution to update cache items with new values.

Firstly, I highly recommend to see this video course of PluralSight about caching if you have not seen it until now, because I will expose my idea about caching at the top of the written sample application inside this video course.

Caching in the .NET Stack: Inside-Out
Also, you can download the sample application of this course here

If you download the project and also the video course of pluralsight, you will see the caching system has been implemented as a cross-cutting concern and using AOP(Aspect Oriented Programming). In this way, by adding an attribute at the top of each method of classes and also changing some configuration inside the web.config we will be able to cache result of functions as simple as you can imagine.
So, what I am going to talk about caching system right now? By looking carefully, at this comprehensive application, you will figure out that a really vital key point about caching system has been missed. I mean, refreshing the values of cache after changing each object. In other word, the best strategy for caching expiration.

When we are designing a caching system, and with regard to expiration strategy of cache values, we can categorize the whole domain objects to two main parts.
    1) Dependent Objects     2) Independent Objects

1- Dependent Object: The cache values life cycle of these object depends on other objects. It means, if the value of other related objects that have any dependency with this object had been changed, we have to refresh the value of this object’s cache. For instance, cache value of Order table for one customer should be refreshed if the price of order’s goods has been changed.

2- Independent Object: The cache values of these objects are being changed just on their value changing. It means, we should consider cache value refreshing on their value changing, no other objects. For example, basic tables like Gender, Currency Rate, Assets and etc. We just try to update cache values of Currency Rate as soon as some values inside its object has been changed.

Managing and maintaining the Independent objects are totally straight forward. Typically, on their saving methods, after updating related tables in the database we will update cache values and also on getting value methods, we can return value from cache system.
But for the dependent objects the scenario of maintaining cache values cannot implement as simple as independent objects, especially if we are using POCO objects for Domain Model rather than popular ORMs like Entity Framework or N-Hibernate.
Just Assume this fact that ,there are a lot of Grid Views and Business Rules inside our applications that are using tables, views or store procedures to show data for End-Users or implement business logic, while different kinds of data should be fetched from cache system.

How we are going to maintain and refresh cache values if one dependency of objects has been changed? Can we always return cache values for some views or store procedures in these cases? This is my suggested approach for this kind of occasion.

First of all look at the below table.

Cache Category


Cache Key

Person

Customer,

Address,

BasketOrder,

Some Store Procedure names,

Some View names,

etc...

Product

ProductInfo,

Stock,

Some Store Procedure names,

Some View names,

etc...


As you can see in the above table we have designed a two level dictionary of Cache Category and Cache key for dependent objects. In general view, we will save object values inside the cache system using cache key and also whenever an object is going to be updated, we will find the Cache category of that object and expired all the keys inside that specific category.

Consequently, On retrieving methods of data layer, we just check the cache system, and if a key is existed inside the cache system, the value will return back, otherwise we will query the database for values and put the result in cache. Also, on updating methods, we will test if it is dependent objects or not. If it is, after updating the database record, the whole second level of cache keys will be expired. In simple terms, we can maintain independent objects inside the cache system via one unique key - which can come from function name - while for sophisticated domain model with dependent object, a dictionary of category and keys should be implemented, to maintain relation between different objects on when we are going to expire current cache values.