Проблема кэша 2-го уровня NHibernate с повторным запросом

#nhibernate #fluent-nhibernate

#nhibernate #свободно-nhibernate

Вопрос:

У меня кэш 2-го уровня работает отлично, когда я использую Session.Get(), однако, если я использую новый API-интерфейс для переадресации запросов в NH3.0, кеш не попадает.

Это работает отлично:

 public TEntity Get(int id)
{
  return session.Get<TEntity>(id);
}
  

Это не попадает в кеш:

 public TEntity Get(Expression<Func<TEntity bool>> filter)
{
    var query = _session.QueryOver<TEntity>()
                .Where(filter);

    query.Cacheable();     
    return query.SingleOrDefault();
}
  

Я использую транзакции, чтобы убедиться, что кеш 2-го уровня используется правильно.

Вот моя конфигурация сеанса:

 Session = Fluently.Configure()
                .Database(SQLiteConfiguration.Standard.InMemory().ShowSql())
                .Mappings(x => x.FluentMappings.AddFromAssemblyOf<Activity>())
                .Cache(c => c.UseSecondLevelCache()
                            .UseQueryCache()
                            .ProviderClass<NHibernate.Cache.HashtableCacheProvider>())
                .ExposeConfiguration(cfg => configuration = cfg)
                .BuildSessionFactory()
                .OpenSession();
  

Я настраиваю свои объекты для использования кеша:

 public class CommentMap : ClassMap<Comment>
    {
        public CommentMap()
        {
            Cache.ReadWrite();

            Id(x => x.Id);
            Map(x => x.Message);
            References(x => x.Activity);
            References(x => x.User);
        }
    }
  

Я вызываю метод кэширования в своих запросах QueryOver:

 public TEntity Get(Expression<Func<TEntity, bool>> filter)
        {
            var query = _session.QueryOver<TEntity>()
                .Where(filter);

            query
                .Cacheable();

            return query.SingleOrDefault();
        }
  

Должно быть, я что-то упускаю, просто не могу понять, что.

Комментарии:

1. Примечание для всех читателей после меня! Вопрос, похоже, был отредактирован, чтобы отразить правильную реализацию, поэтому, вероятно, ответ Diegos отмечен как правильный…

Ответ №1:

Существует несколько связанных проблем:

  • Session.Load никогда не попадает в БД, поэтому это не является доказательством того, что кеширование работает
  • Кэш запросов включен отдельно от кэша объектов
  • Кэширование запросов является явным: вы должны указать NHibernate для кэширования, QueryOver используя Cacheable() метод

Кроме того, убедитесь, что у вас есть кэширование сущностей для сущностей, запросы которых вы будете кэшировать. В противном случае кеширование ухудшит ситуацию.

Комментарии:

1. У меня включены кэши запросов и сущностей, и я вызываю метод Cacheable() при переадресации запросов. В понедельник я сверю ваш список с кодом, чтобы узнать, не пропустил ли я что-то. Спасибо.

2. В конце концов, в чем была проблема? Было ли это, что у вас был запрос. Cacheable() с последующим возвратом запроса. SingleOrDefault() (вместо того, чтобы выполнять запрос = запрос. Cacheable())? Или вы нашли что-то еще.