6

We have a number of cache regions set up in our nHibernate implementation. In order to avoid trouble with load balanced web servers, I want to effectively disable the caching on the pages that edit the cached data. I can write a method that clears out all my query caches, my class caches and my entity caches easily enough.

But what I really want is to clear the cache by region. sessionFactory.EvictQueries() will take a region parameter, but Evict() and EvictCollection() does not. I don't really want to throw away the whole cache here, nor do I want to maintain some sort of clumsy dictionary associating types with their cache regions. Does nHibernate have a way to ask an entity or collection what its caching settings are?

thanks

Ted
  • 113
  • 5
  • Hey @Ted, it sounds like you're trying to do something manually that you can already wire up. Is there a reason that you are not setting up some kind of cache dependency to automatically evict items when a change is made to the data store? Like a SqlCacheDependency? – swannee Feb 24 '12 at 17:06
  • or even better- use a distributed cache? nHibernate supports those – J. Ed Feb 24 '12 at 22:54
  • I'd love to use a distributed cache but the customers are not keen, for stupid customer reasons. I am looking into CacheDependency now, though we're using Oracle so the specific SQL Server implementation is no use to me. Looks like the generic implementation of dbCacheDependency works by polling, and relies on some OLEDB stuff. Is that performant? does it have implications for my driver choices? I'm looking at 3rd party Oracle drivers like DataDirect and Devart as well as ODP.NET. – Ted Feb 27 '12 at 10:37
  • So ,dbCacheDependency isn't an option for me either as we're fairly heavily restricted in terms of the database changes we can make at this point, and the Oracle implementation relies on a whole set of triggers and auxiliary tables to do its thing. The thing is, nHibernate _nearly_ gives me the information I need - its easy to get hold of metadata for my entities and collections. All I need is to access the tag within it..... – Ted Feb 27 '12 at 11:18

2 Answers2

6

I've just done the same thing. For everyone's benefit, here is the method I constructed:

public void ClearCache(string regionName)
    {
        // Use your favourite IOC to get to the session factory
        var sessionFactory = ObjectFactory.GetInstance<ISessionFactory>();

        sessionFactory.EvictQueries(regionName);

        foreach (var collectionMetaData in sessionFactory.GetAllCollectionMetadata().Values)
        {
            var collectionPersister = collectionMetaData as NHibernate.Persister.Collection.ICollectionPersister;
            if (collectionPersister != null)
            {
                if ((collectionPersister.Cache != null) && (collectionPersister.Cache.RegionName == regionName))
                {
                    sessionFactory.EvictCollection(collectionPersister.Role);
                }
            }
        }

        foreach (var classMetaData in sessionFactory.GetAllClassMetadata().Values)
        {
            var entityPersister = classMetaData as NHibernate.Persister.Entity.IEntityPersister;
            if (entityPersister != null)
            {
                if ((entityPersister.Cache != null) && (entityPersister.Cache.RegionName == regionName))
                {
                    sessionFactory.EvictEntity(entityPersister.EntityName);
                }
            }
        }
    }
antmeehan
  • 865
  • 9
  • 11
0

OK, looks like i've answered my own question. The default interface that's returned when you pull out the nHibernate metadata doesn't provide information on caching, however if you dig around in the implementations of it, it does. A bit clumsy, but it does the job.

Ted
  • 113
  • 5