大家都知道会话中有缓存。 这种缓存通常可以通过两种方法来清除:NHibernate驱逐编号
- Session.Evict
- Session.Clear
第二种方法去除不仅单次入境的所有缓存。
我有商业方法。它接收大对象的id(来自aspx站点)或有时候有几个id。在数据库中执行原生的sql操作(使用具有复杂逻辑的sql-query不加载C#中的所有数据)。然后我需要使缓存无效。因此,每个潜在的对象负载都不会从数据库直接缓存。
不幸的是驱逐只接受对象。此外,它的实现DefaultEvictEventListener在代码路径中有明确的分离 - 对于代理而不是代理类是分开的。我试图简单地创建实体,手工填写id并将其传递给Evict。这不会起作用。正如我所了解的Evict by not proxied class,使用GetHashCode从缓存中查找和删除对象。所以如果我不覆盖它,它不会起作用。我有很多原生的sql批处理操作,因此覆盖所有实体对象中的所有GetHashcode将创建大量工作。此外,我不确定这种情况是否从缓存或不删除代理。 更新:据我试图为我重写GetHashCode也没有帮助。 StatefulPersistenceContext.RemoveEntry找不到实体,因为它使用RuntimeHelpers.GetHashCode。因此,该解决方案甚至是不可能的
使用NHibernate我产生了以下解决方案来源:
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);
}
}
它只是使用NHibenate实现的一部分。但在我看来,复制代码似乎不是个好主意。可能有人有其他想法?
这是正确的做法。获取返回模型的代理并设置ID – jonnii 2010-11-05 15:26:28
我正在谈论第一级缓存。 我不确定它是否在缓存或否。有时它有时不是。 在这种情况下,我想从缓存中清除它。如果它不在缓存中,你的代码可能会对数据库产生真正的影响。所以我想要这两种情况下相同的代码。所以数据操纵操作只是确保缓存中没有数据。 – 2010-11-05 15:29:15
关于上次“编辑回应评论”。如果在操作时它不会在Evict内部访问数据库,并且没有在缓存中的实体没有例外,那么我会说你的解决方案是最好的。 – 2010-11-05 15:50:57