2009-09-18 64 views
2

不同的NHibernate会话可能共享一个第一级缓存吗?我试图用拦截器和听众来实现它。除了Session.Evict()之外,所有的工作都很好。在不同会话之间共享一级缓存?

public class SharedCache : 
    EmptyInterceptor, 
    IFlushEntityEventListener, 
    ILoadEventListener, 
    IEvictEventListener, 
    ISharedCache { 
    [ThreadStatic] 
    private readonly Dictionary<string, Dictionary<object, object>> cache; 

    private ISessionFactory factory; 

    public SharedCache() { 
     this.cache = new Dictionary<string, Dictionary<object, object>>(); 
    } 

    public override object Instantiate(string clazz, EntityMode entityMode, object id) { 
     var entityCache = this.GetCache(clazz); 
     if (entityCache.ContainsKey(id)) 
      return entityCache[id]; 

     var entity = Activator.CreateInstance(Type.GetType(clazz)); 
     this.factory.GetClassMetadata(clazz).SetIdentifier(entity, id, entityMode); 
     return entity; 
    } 

    private Dictionary<object, object> GetCache(string clazz) { 
     if (!cache.ContainsKey(clazz)) 
      cache.Add(clazz, new Dictionary<object, object>()); 

     return cache[clazz]; 
    } 

    public void Configure(Configuration config) { 
     config.SetInterceptor(this); 
     config.SetListener(ListenerType.FlushEntity, this); 
     config.SetListener(ListenerType.Load, this); 
     config.SetListener(ListenerType.Evict, this); 
    } 

    public void Initialize(ISessionFactory sessionFactory) { 
     this.factory = sessionFactory; 
    } 

    public void OnFlushEntity(FlushEntityEvent ev) { 
     var entry = ev.EntityEntry; 

     var entityCache = this.GetCache(ev.EntityEntry.EntityName); 

     if (entry.Status == Status.Deleted) { 
      entityCache.Remove(entry.Id); 
      return; 
     } 

     if (!entry.ExistsInDatabase && !entityCache.ContainsKey(entry.Id)) 
      entityCache.Add(entry.Id, ev.Entity); 
    } 


    public void OnLoad(LoadEvent ev, LoadType loadType) { 
     var entityCache = this.GetCache(ev.EntityClassName); 

     if (entityCache.ContainsKey(ev.EntityId)) 
      ev.Result = entityCache[ev.EntityId]; 
    } 

    public void OnEvict(EvictEvent ev) { 
     var entityName = ev.Session.GetEntityName(ev.Entity); 
     var entityCache = this.GetCache(entityName); 
     var id = ev.Session.GetIdentifier(ev.Entity); 

     entityCache.Remove(id); 
    } 

} 
+1

为什么? – 2009-09-18 14:49:29

+0

通常由于nhibernate会话不是线程安全的。所以应该在每个线程中打开会话。但也需要一级缓存。所以我决定在会话中创建自己的第一级缓存。 – SHSE 2009-09-18 15:03:18

+1

如果您需要跨会话缓存,为什么不使用第二级缓存? – 2009-09-18 19:10:36

回答

2

,如果你想分享你应该使用2级高速缓存与会话工厂进入一个高速缓存中没有1RST级或会话缓存不能共享 - see the docs

你必须要小心,因为缓存如果数据在nhibernate会话之外更改,例如通过触发器或其他客户端 - 或另一台计算机上运行的代码的另一个实例,将不会失效

相关问题