Поделиться кешем первого уровня между разными сессиями? - PullRequest
2 голосов
/ 18 сентября 2009

Возможно ли для разных сессий NHibernate использовать один кэш 1-го уровня? Я пытался реализовать это с помощью перехватчиков и слушателей. Все отлично работает, кроме 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 Ответ

2 голосов
/ 01 октября 2009

Ни один кэш первого уровня или сеанса не может быть общим, если вы хотите использовать кеш общего пользования, вам следует использовать кэш 2-го уровня, который соответствует фабрике сессий - см. Документы

вы должны быть осторожны, так как кеш не будет признан недействительным, если данные изменяются вне сеансов nhibernate, например, с помощью триггеров или другого клиента - или другого экземпляра вашего кода, работающего на другой машине

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...