【发布时间】:2012-01-06 16:42:49
【问题描述】:
我有一个相当简单的条件查询来获取子集合,如下所示:
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)。
谷歌搜索发现了许多古老的问题,例如:
- NH-195: Child collections are not being stored in the second level cache
- Syscache2 2nd level cache: Child coll. objects requeried
- Weird differences between SysCache and SysCache2
- NHibernate – Beware of inadvisably applied caching strategies(Ayende - 当然他只是懒得提不做什么,而不是如何解决它...)
但是,这些似乎都在很久以前就已经修复了,无论我使用哪个提供商,我都会遇到同样的不良行为。
我已经阅读了nhibernate.info documentation on SysCache and SysCache2,似乎没有任何我遗漏的内容。我已经尝试将cacheRegion 行添加到查询中涉及的所有表的Web.config 文件中,但它没有改变任何东西(并且AFAIK 这些元素只是为了使缓存无效,所以无论如何,它们应该无关紧要)。
鉴于所有这些似乎都已修复/解决的超级老问题,我认为这不可能仍然是 NHibernate 中的错误,它一定是我正在做的事情错误的。但是什么?
在将 NHibernate 中的 fetch 指令与二级缓存相结合时,我需要做些什么特别的事情吗?我在这里错过了什么?
【问题讨论】:
-
你使用的是无状态会话吗?
-
@Origin:不,实际上这是未来查询序列的一部分,并且在无状态会话中不可用。无论如何,无状态会话不会以这种方式运行,它只会每次都执行原始查询。
标签: .net nhibernate syscache2