NHibernate-запрос пропускает кэш запроса после сохранения нового объекта

у меня есть NHibernate (с NHibernate на.В LINQ и Свободно NHibernate) настройка с кэшированием запросов. Все работает нормально, пока я не сделаю session.Save(new Widget()) (т. е. SQL INSERT). После этого момента все запросы на этот тип Widget пропустить кэш запросов. Запросы на другие типы сущностей кэшируются просто отлично.

using (ISession session = MySessionFactory.OpenSession())
{
    using (var transaction = session.BeginTransaction())
    {
        // this INSERT screws things up
        var widget = new Widget {Name = "Foo"};
        session.Save(widget);

        var query = (from w in session.Query<Widget>().Cacheable()
                     where w.Name == "Bar"
                     select w);

        var fetched1 = query.FirstOrDefault();
        var fetched2 = query.FirstOrDefault(); // miss?!

        transaction.Commit();
    }
}

если я начну новый Transaction проблема сохраняется. Если я начну новый Session, проблема исчезнет. Это кажется немного странным, так как понимание было кэш второго уровня получает сброс за SessionFactory (не Session).

Я не думаю, что это имеет значение, но я использую HashtableCacheProvider, так как я просто тестирую прямо сейчас.

1 ответов


поведение, которое вы описали, является правильным (здесь).

обновление кэша метка не обновляется до фиксации сделка! Это необходимо для того, чтобы вы не читали " uncommitted значения" из кэша.

всякий раз, когда есть изменение на type которые у нас есть в кэше-кэшированные данные являются устаревшими... до завершения транзакции.

представьте, что вы кэшировали результаты этого фильтра:

 var query = (from w in session.Query<Widget>().Cacheable()
  where w.Name == "B*" // all names starting with B
  select w);

и позже добавит новый виджет:

var widget = new Widget {Name = "Brigitte"};
session.Save(widget);
// explicit Flush is not needed, 
// but then, until Commit(), query will never return Brigitte
session.Flush(); // to immediately execute INSERT

Если запрос будет по-прежнему кэшироваться, Brigitte никогда не появится...

и в то время как в транзакции запросы с FirstOrDefault() выполняются немедленно - операции записи могут ждать Флеша при фиксации.

из-за транзакции все содержащиеся операции (insert, udpate, select) не могут получать прибыль от кэширования, потому что только транзакция как пакет делает чувство. Поэтому, пока commit не будет вызван, кэш не может использоваться.

многие подробные и очень полезная информация может быть найдена здесь:кэширование первого и второго уровней в NHibernate

кэш временных меток обновляется всякий раз, когда таблица записывается, но сложным способом:

  • когда мы выполняем пишем, мы пишем значение, которое находится где-то в будущем в кэш. Поэтому все запросы, которые попали в кэш теперь будет не найдите его, а затем нажмите DB, чтобы получить новые данные. Поскольку мы находимся в середине сделки, они будут ждать, пока мы завершите транзакцию. Если мы используем низкий уровень изоляции, и другой поток / машина пытается вернуть старые результаты в кэш, он не будет держать, потому что метка времени обновления находится в будущее.
  • когда мы выполняем фиксацию транзакции, мы обновляем кэш временных меток текущим значением.