2011-12-27 6 views
0

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

Но если я звоню RetrieveAll, а затем RetrieveByPrimaryKey с некоторыми ПК, я вижу два выданных оператора 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; 
    } 

ответ

0

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

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

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

+0

Спасибо за ваш ответ и ссылку. Теперь все ясно. Счастливого Нового года! –