【发布时间】:2010-11-05 15:01:50
【问题描述】:
大家都知道会话中有缓存。 这个缓存一般可以通过2种方法清除:
- 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 实现的一部分。但在我看来,复制代码并不是一个好主意。可能有人有其他想法吗?
【问题讨论】:
标签: nhibernate