Замок 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
Можно использовать элементы, кэшированные другими запросами.
Вот хороший пост в блоге от Айенде об этом.