Как заставить NHibernate кэшировать найденные дочерние коллекции?

У меня есть довольно простой критериальный запрос, который извлекает дочерние коллекции, например, так:

var order = Session.CreateCriteria()
    .Add(Restrictions.Eq("Id", id))
    .SetFetchMode("Customer", FetchMode.Eager)
    .SetFetchMode("Products", FetchMode.Eager)
    .SetFetchMode("Products.Category", FetchMode.Eager)
    .SetCacheable(true)
    .UniqueResult();

Используя 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).

Погуглив, я обнаружил ряд древних проблем, таких как:

Однако, все эти проблемы, похоже, были исправлены давным-давно, и я получаю такое же плохое поведение независимо от того, какого провайдера я использую.

Я прочитал документацию nhibernate.info по SysCache и SysCache2 и, похоже, ничего не упустил. Я пробовал добавлять строки cacheRegion в файл Web.config для всех таблиц, участвующих в запросе, но это ничего не меняет (и AFAIK эти элементы нужны только для аннулирования кэша, так что они не должны иметь значения в любом случае).

Учитывая все эти суперстарые проблемы, которые, похоже, все исправлены/решены, я решил, что это не может все еще быть ошибкой в NHibernate, это должно быть что-то, что я делаю неправильно. Но что?

Есть ли что-то особенное, что мне нужно делать при комбинировании инструкций выборки в NHibernate с кэшем второго уровня? Что я здесь упускаю?

14
задан Frédéric 2 May 2017 в 18:19
поделиться