2009-09-18 85 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會話之外更改,例如通過觸發器或其他客戶端 - 或另一臺計算機上運行的代碼的另一個實例,將不會失效

相關問題