我有一个相当简单的标准查询来获取子集合,如下所示:
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:子集合未存储在二级缓存中
- Syscache2 二级缓存:Child coll. 请求的对象
- SysCache 和 SysCache2 之间的奇怪差异
- NHibernate——提防不明智的缓存策略(Ayende——当然他只是懒得提什么不该做,而不是如何修复它……)
但是,这些似乎都是很久以前修复的,无论我使用哪个提供程序,我都会遇到同样的不良行为。
我已经阅读了关于 SysCache 和 SysCache2 的 nhibernate.info 文档,似乎没有任何我遗漏的东西。我已经尝试为查询中涉及的所有表添加cacheRegion
行到Web.config
文件中,但它不会改变任何东西(并且AFAIK这些元素只是为了使缓存无效,所以它们无论如何都不重要)。
由于所有这些似乎都已修复/解决的超级老问题,我认为这不可能仍然是 NHibernate 中的错误,它一定是我做错了。但是什么?
将 NHibernate 中的 fetch 指令与二级缓存相结合时,我需要做些什么特别的事情吗?我在这里想念什么?