我们广泛使用 NHibernate 多查询功能并遇到奇怪的行为。似乎 NHibernate 不缓存多查询,它们总是命中数据库。我们正在使用 QueryOver,所有查询都设置为可缓存,但是当使用blitz.io使用模式测试主页时,-p 1-250:30
我可以看到唯一命中数据库的多查询被执行了 2000 多次,而其他查询(如选择当前登录的用户)只执行一次或两次。
所以问题是:我是否遗漏了什么或者 NHibernate 并没有真正缓存多查询结果?
我们广泛使用 NHibernate 多查询功能并遇到奇怪的行为。似乎 NHibernate 不缓存多查询,它们总是命中数据库。我们正在使用 QueryOver,所有查询都设置为可缓存,但是当使用blitz.io使用模式测试主页时,-p 1-250:30
我可以看到唯一命中数据库的多查询被执行了 2000 多次,而其他查询(如选择当前登录的用户)只执行一次或两次。
所以问题是:我是否遗漏了什么或者 NHibernate 并没有真正缓存多查询结果?
啊哈,明白了!事实证明,这并不是所有二级缓存的错,而是我们对 QueryOver 的使用是罪魁祸首。
当我们正在编写一个多租户 SaaS 应用程序时,我们的大多数查询看起来像这样:
return
Session.QueryOver<Article>().Cacheable().
Where(a => a.Site == site && a.PublishedAt <= publishedAt).
OrderByCoalesceDesc(typeof(DateTime), a => a.UpdatedAt, a => a.CreatedAt).
Take(count).
Future();
这a.Site == site
就是问题所在。显然,查询缓存检查查询结果是否被缓存的方式基本上是使用一条SQL语句和所有参数的组合作为缓存“哈希表”的键。对于我们的多查询,SQL 语句文本总是相同的,但site
参数是罪魁祸首。NH 检查所有提供的参数是否与已经在缓存中的参数匹配,当然我们没有Equals()
在我们的Site
类中实现,所以检查总是失败。
我们最终得到的是像这样重写我们的查询:
var siteID = site.ID;
return
Session.QueryOver<Article>().Cacheable().
Where(a => a.Site.ID == siteID && a.PublishedAt <= publishedAt)...