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

Я просто делаю некоторые эксперименты на 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 ответ

Решение

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

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

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

Другие вопросы по тегам