每个人都知道会话中有缓存.通常可以通过2种方法清除此缓存:
第二种方法不仅删除单个条目的所有缓存.
我有商业方法.它接收大对象的id(来自aspx站点)或有时是几个id.并在数据库中执行本机sql操作(使用具有复杂逻辑的sql-query来不加载C#中的所有数据).然后我需要使缓存无效.因此,对象的每个潜在负载都不会直接从数据库中缓存.
不幸的是,evict只接受对象.此外,它的实现DefaultEvictEventListener在代码路径中有明显的分离 - 对于代理而不是代理类是分开的.我试过简单地创建实体,手动填充id并将其传递给Evict.这不行.据我所知,Evict没有代理类使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
它只是使用NHibenate实现的一部分.但在我看来重复代码并不是一个好主意.可能有人有其他想法吗?
如果您确定该对象位于缓存中,Session.Get(id)则不会命中该数据库.这可能是最容易做到的,然后Evict是你得到的对象:
Model m = Session.Get(id);
Session.Evict(m);
Run Code Online (Sandbox Code Playgroud)
编辑
我不清楚你是在谈论第一级缓存还是第二级缓存.以上将从第一级缓存中逐出.要从二级缓存中逐出,请使用evict方法SessionFactory.
编辑以回应评论
在这种情况下,您可以尝试Session.Load:
Model m = Session.Load(id);
Session.Evict(m);
Run Code Online (Sandbox Code Playgroud)
如果m在缓存中,Session.Load将返回您可以逐出的实例.如果不是,则返回代理(没有数据库命中).我的测试表明,Session.Evict如果你试图驱逐代理,不会抛出,所以这应该工作.
| 归档时间: |
|
| 查看次数: |
5022 次 |
| 最近记录: |