在不同会话之间共享第一级缓存?

时间:2009-09-18 14:11:04

标签: c# .net nhibernate session caching

不同的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 个答案:

答案 0 :(得分:2)

如果您要共享缓存,则无法共享第一级或会话缓存,您应该使用与会话工厂一起使用的二级缓存 - see the docs

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