У меня есть довольно простой запрос критериев, который извлекает дочерние коллекции, например:
var order = Session.CreateCriteria<Order>()
.Add(Restrictions.Eq("Id", id))
.SetFetchMode("Customer", FetchMode.Eager)
.SetFetchMode("Products", FetchMode.Eager)
.SetFetchMode("Products.Category", FetchMode.Eager)
.SetCacheable(true)
.UniqueResult<Order>();
Используя NH Prof, я проверил, что это делает только одну поездку в оба конца в базу данных (как и ожидалось) с холодным кешем; однако при последовательных запусках он извлекает из кэша только Order
и затем обращается к базе данных с помощью SELECT (N + 1) для каждого дочернего объекта на графике, как в:
Cached query: SELECT ... FROM Order this_ left outer join Customer customer2 [...]
SELECT ... FROM Customer WHERE Id = 123;
SELECT ... FROM Products WHERE Id = 500;
SELECT ... FROM Products WHERE Id = 501;
...
SELECT ... FROM Categories WHERE Id = 3;
И так далее и так далее. Очевидно, что это не кеширование всего запроса или графика, а только корневой объект. Первая строка "кэшированного запроса" на самом деле имеет все условия join
, которые она предположила, - она определенно правильно кэширует запрос, а не сущности, видимо.
Я пробовал это, используя SysCache, SysCache2 и даже поставщики кэша HashTable, и я всегда, кажется, получаю такое же поведение (NH версия 3.2.0).
В Googling появился ряд древних проблем, таких как:
- NH-195: коллекции детей не хранятся в кэше второго уровня
- Syscache2 Кэш второго уровня: дочерний колл. отправленные объекты
- Странные различия между SysCache и SysCache2
- NHibernate - Остерегайтесь нецелесообразно применяемых стратегий кэширования (Айенде - конечно, он только упоминает, что не делать, а не как исправить это...)
Тем не менее, все они, кажется, были исправлены давным-давно, и я получаю такое же плохое поведение, независимо от того, какой провайдер я использую.
Я прочитал документацию nhibernate.info на SysCache и SysCache2, и, похоже, я ничего не теряю, Я пробовал добавлять строки cacheRegion
в файл Web.config
для всех таблиц, участвующих в запросе, но ничего не меняет (и AFAIK эти элементы просто являются недействительными для кеша, поэтому они не должны иметь значения, так или иначе).
Со всеми этими супер-старыми проблемами, которые все, кажется, исправлены/решены, я полагаю, что это, возможно, все еще может быть ошибкой в NHibernate, это должно быть то, что я делаю неправильно. Но что?
Есть ли что-то особенное, что мне нужно сделать, комбинируя команды извлечения в NHibernate с кешем второго уровня? Что мне здесь не хватает?