Замок ActiveRecord - кэш 2-го уровня - нужно объяснение этого поведения - PullRequest
0 голосов
/ 27 декабря 2011

Я просто провожу несколько экспериментов с Castle AR и кешем 2-го уровня NH.В следующих двух методах я вижу, что кэширование работает нормально, но только для повторения вызова каждого из них.Другими словами, если я вызываю RetrieveByPrimaryKey дважды для одного и того же ПК, объект находится в кеше.И если я вызываю RetrieveAll дважды, я вижу, что SQL выдается только один раз.

Но если я вызываю RetrieveAll, а затем RetrieveByPrimaryKey с некоторым PK, я вижу, как выдаются два оператора SQL.У меня вопрос: почему AR не ищет эту сущность в кеше?Конечно, он нашел бы его там в результате предыдущего вызова RetrieveAll.

    public static T RetrieveByPrimaryKey(Guid id)
    {
        var res = default(T);
        var findCriteria = DetachedCriteria.For<T>().SetCacheable(true);
        var eqExpression = NHibernate.Criterion.Expression.Eq("Id", id);
        findCriteria.Add(eqExpression);
        var items = FindAll(findCriteria);
        if (items != null && items.Length > 0)
            res = items[0];
        return res;
    }

    public static T[] RetrieveAll()
    {
        var findCriteria = DetachedCriteria.For<T>().SetCacheable(true);
        var res = FindAll(findCriteria);
        return res;
    }

1 Ответ

0 голосов
/ 28 декабря 2011

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

nHibernate (кстати, это не имеет ничего общего с AR) не знает, что логически , один запрос «содержит» другой.вот почему вы получаете 2 дБ поездки.

Я бы предложил использовать ISession.Get для получения элементов по идентификатору (это рекомендуемый метод).Я думаю (хотя и не проверял), что Get может использовать элементы, кэшированные другими запросами.
вот хорошее сообщение в блоге от ayende об этом.

...