February 12, 2010

If your application uses NHibernate in a web farm, there is already a second-level cache provider that you ought to be familiar with: NHibernate.Caches.SysCache2, which supports expiration based on SQL table or command-based dependencies. Whilst this is a decent solution, it does cause your whole cache region to be invalidated when data changes in the table.

It may be more ideal for you to invalidate the cache on a per-object basis, i.e., if one web server in the farm receives a request that causes a cached object to change, the portion of the application running on that server should be able to expire that object from the cache of all other servers within that farm.

A technique that I have used somewhat successfully is a shared disk cache invalidation mechanism called FileSysCache, similar to the “File Update Model” discussed in this MSDN library article. Unlike the technique in that article, however, ours does not suffer from the issues arising from SQL Server trying to access the file system. Our method creates a zero-length file on the shared disk, together with a CacheDependency to that file, for each cacheable object. It deletes that file when the cache is invalidated for that object. Thus, any other servers holding a cached copy of that object will have a CacheDependency on the same file, and their cached copies will expire.

This happens behind the scenes for you as an application developer. NHibernate will call the relevant methods in the caching provider; all you need to know is that to expire the object across the web farm, you just need to evict it from the second level cache, using:

Hello Daniel… looking for some insight or ideas on what an issue might be. We are running a webfarm of up to 8 servers on an older .net 2.0 project. Using Nhibernate 1.2.0xx. We have installed the FileSysCache, Syscache and Nhibernate dlls into our bin folders. We shared a directory out to the 8 servers as in “\\server\SharedcacheFolder” in our web.config. The issue we are encountering is that in Pre prod on two servers we don’t get ANY errors. On our prod using 4 servers, we get the following ‘You may not dereference an collection with cascade=”all-delete-orphan”‘. My question as per Pab is once again to confirm.. you should set your — filesyscache path=”\\server\sharedCacheFolder”/–. We are scratching our heads trying to look for ideas. Is it an issue that we are using the same sharedcachefolder for both PreProd and Prod? Thanks for any ideas.

Hi Daniel. We spoke too soon wrt to the Pre Prod enviro. It is also failing. An interesting note is that when we inherited this issue we noted that the lazy setting was set to “false” in the mappings. As the hibernate was failing already we changed it to “true”. This has aggravated the situation. Now we get failure even without the filesyscache running. We are down to assuming it is a code bug of some type.