Everyone knows that there is cache in session. This cache generally could be cleared by 2 methods:
- Session.Evict
- Session.Clear
Second method removes all cache not only for single entry.
I have business method. It receives id of large object (from aspx site) or sometimes several ids. And do native sql operation in database (using sql-query with complex logic to not load all data in C#). Then I need to invalidate cache. So every potential load of object goes without cache direct from database.
Unfortunately evict accepting only objects. Also its implementation DefaultEvictEventListener has clear separation in code path - separate for proxy and not proxied classes. I have tried simply to create entity, fill id manually and pass it to Evict. This will not works. As I understand Evict by not proxied class use GetHashCode to find and remove object from cache. So if I am not overriding it it will not works. I have a lot native sql batch operations so overriding all GetHashcode in all entities objects will create a lot of work. Also I am not sure is this case removes proxies from cache or no. Update: As far as I have tried for me overriding GetHashCode also not helped. StatefulPersistenceContext.RemoveEntry not found entity because it uses RuntimeHelpers.GetHashCode. So this solution is not even possible
Using sources of NHibernate I have produced following solution:
public static class NHSessionHelper: DefaultEvictEventListener
public static void RemoveEntityFromCache(this ISession session, Type type, object entityId)
{
ISessionImplementor sessionImpl = session.GetSessionImplementation();
IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;
IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(type.FullName);
if (persister == null)
{
return;
}
EntityKey key = new EntityKey(entityId, persister, sessionImpl.EntityMode);
persistenceContext.RemoveProxy(key);
object entity = persistenceContext.RemoveEntity(key);
if (entity != null)
{
EntityEntry e = persistenceContext.RemoveEntry(entity);
DoEvict(entity, key, e.Persister, (IEventSource)sessionImpl);
}
}
It just uses part of NHibenate implementation. But it seem to me not good idea to duplicate code. May be anyone have other ideas?