【发布时间】:2013-01-07 09:48:53
【问题描述】:
我正在使用具有 Fluent NHibernate 的二级缓存提供程序 SysCache2,使用标准的 fluent 配置(启用查询缓存,这似乎是一般建议),并以通常的方式定义基于表的依赖项。
流利:
config.Cache(c => c
.ProviderClass<NHibernate.Caches.SysCache2.SysCacheProvider>()
.UseQueryCache()
.UseSecondLevelCache()
.UseMinimalPuts()
)
Web.Config:
<cacheRegion name="User" relativeExpiration="7200">
<dependencies>
<tables>
<add name="User" databaseEntryName="OldClient" tableName="tbl_users" />
</tables>
</dependencies>
用户映射:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Table("Users");
....
// caching
Cache.IncludeAll().ReadWrite().Region("Users");
}
}
对于单个请求,一切都按预期运行,即:
Session<User>.Get()
正如NHibernate caches by ID 所期望的那样。后续请求不会命中数据库,而使数据库中的记录失效会导致Entity失效,从而导致在下一次请求期间进行后续的SQL调用。没事。
问题在于查询缓存。首先,一切正常。执行调用如:
Session<User>.Query(item => item.Active == true)
按照您的预期导致 SQL 调用(SELECT * FROM Users WHERE Active = true)。随后的执行不会导致 SQL。伟大的。直到查询集中的单个记录在数据库中发生更改。执行相同的查询会产生一个 SELECT N+1:
SELECT * FROM Users WHERE ID = 1
SELECT * FROM Users WHERE ID = 2
SELECT * FROM Users WHERE ID = 3
SELECT * FROM Users WHERE ID = 4
...
我在其他地方找到了对此的参考,尽管没有解决方案:
StackOverflow - How do I make NHibernate cache fetched child collections? 见“多一点”部分
Ayende Caching Strategies 他提到最后确保“实体也被缓存”
目前我可以避免这种情况的唯一方法是在每次请求后清除查询缓存 - 这几乎使它无用。当某个实体无效时,我需要查询缓存来清除该实体的所有内容——而不仅仅是单个记录。
有什么想法吗?
【问题讨论】:
标签: c# nhibernate syscache2