Cache layer

Thanks to AOP concept, creating a cache layer that is transparent to the caller is not a big deal. I have a piece of code that in a loop calls this method

1
2
3
ClientCompetitor competitor = Repository.ClientCompetitor.GetByCriteria(
Query.CreateEq("AssociatedClient", clieid))
.SingleOrDefault();

This is based on a standard implementation of repository and a Specification Pattern as a query model. With nhibernate profiler I see that during the execution of this task, a lot of identical query are issued, because it gets called around 1000 times always with the same clieid.

Now before changing the code of the class to store in a dictionary<ClieId, ClientCompetitor> cached result, I like to handle this with a transparent cache layer used with AOP. This could be achieved registering this interceptor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<component
id="RepositoryCache"
service="Castle.Core.Interceptor.IInterceptor, Castle.Core"
type="xxx.BaseServices.Castle.Cache2Interceptor, xxx.BaseServices"
lifestyle="transient">
<parameters>
<invocationCache>${WindowsCache}</invocationCache>
<Rules>
<dictionary>
<entry key="ClientCompetitor.*GetByCriteria">.classname(ClientCompetitor).absolute(600)</entry>
</dictionary>
</Rules>
</parameters>
</component>

I simply create a Cache2Interceptor object that has a property called Rules to define regular expression to specify witch methods I want to apply cache to. With this configuration I ask to put cache in ClientCompetitor repository and with GetByCriteria method. The cache component use the Specification Pattern object for retrieving the key to the real cache implementation, and I tell cache component that the classname is (ClientCompetitor). The className is used because I can register other method as cache invalidator, as an example I can tell that the method Save of ClientCompetitor repository will invalidate the entire ClientCompetitor class.

When the interceptor is configured, I can simply tell castle to apply it to ClientCompetitor repository class, and the game is done.

Then I rerun the code and only one query gets issued, with no modification to the original code.

alk.