У меня есть отображение для категории:
<class name="Category" table="Category" lazy="true">
<cache usage="read-write"/> // enabled Entity Cache
<id name="CategoryId" column="pk_cat_id">
<generator class="hilo"/>
</id>
<property name="Name" column="name" type="string" length="50" />
<many-to-one name="ParentCategory" class="Category"
column="parent_cat_id" cascade="save-update"/>
<bag name="childCategories" cascade="all" inverse="true">
<key column="parent_cat_id"/>
<one-to-many class="Category"/>
</bag>
</class>
Я написал:
using (ISession sess = factory.OpenSession())
using (ITransaction tran = sess.BeginTransaction())
{
IList<Category> products = sess.CreateCriteria(typeof(Category))
.SetCacheable(true)
.List<Category>(); // hits DB -- no issues
IList<Category> prod = sess.CreateCriteria(typeof(Category))
.SetCacheable(true)
.Add(Restrictions.Eq("CategoryId", 4128768))
.List<Category>(); // hits DB -- WHY?
tran.Commit();
}
Сверху, как вы можете видеть, для первого запроса он получает все строки в таблице. Второй раз, когда я попытался получить доступ к одной из строк, уже присутствующих в результате первого запроса (CategoryId "= 4128768). Затем, согласно nHibernate, он должен быть в кеше сеанса, и он не должен снова попадать в БД.
Где я ошибаюсь? Я...
Пожалуйста, помогите мне!
То, что вы испытываете, является правильным, потому что на самом деле вы выдаете два разных запроса. Во время выполнения второго запроса - неясно, если /, что второй вернет результат подмножества первого. NHibernate не дает никакого сравнения: запрос без WHERE содержит все результаты в виде запроса с предложением WHERE. Там может быть другая страница, например...
По умолчанию NHibernate выполняет кэширование запросов (с теми же параметрами) и приведенный набор возвращаемых идентификаторов. Для каждого идентификатора существует также кэш объектов. Итак, если вы загружаете материал лениво, используется уже загруженный объект (кэшированный на первом уровне по его идентификатору).
Но в этом случае - оба вопроса не совпадают. У них есть разные параметры (а также - в общем - уже может произойти какая-то операция записи внутри одной и той же транзакции)
.Add(Restrictions.Eq("CategoryId", 4128768))
session.Get<TEntity>(id)
. Когда мы вызываемsession.CreateCriteria()
это кеш запросов. Правда в том, что элементы, загружаемые каждым запросом, кэшируются в кеше сущности (по идентификатору). Но поскольку вы вызвали 2 разных запроса ... оба они должны были быть выполнены. Теперь это имеет больше смысла?