【问题标题】:Why is second level cache not being used for a particular entity?为什么二级缓存不用于特定实体?
【发布时间】:2011-06-01 08:48:52
【问题描述】:

我正在运行 NHibernate Profiler,但我无法弄清楚为什么有些实体正在从二级缓存中检索而有些却没有。

我已经设置了所有必要的东西 - 二级缓存已启用 (SysCache2),对于给我带来问题的实体,缓存设置为只读。我到处都在使用事务。

首先,我的实体如下所示:

Employee { Id, Name, CurrentOffice }

Office { Id, Name }

Team { Id, Name, Office }

其次,这里有一些来自 NH 分析器的示例来演示该问题:

会话 #1

配置文件显示以下 SQL 调用。这是由 Session.Get() 调用生成的:

SELECT office_.Id, office_.Name FROM Office office_WHERE office_.Id = 5

第 2 场会议

在会话 2 中,加载了一名员工,然后在他当前的办公室中引发了一个急切的选择。二级缓存使用正确,因为办公室在 Session #1 中被缓存:

SELECT employee.Id、employee_.Name、employee_.CurrentOfficeId FROM Employee employee_WHERE employee_.Id = 1

二级缓存加载 Office (5 /* id */)

第 3 场会议

接下来会加载一些团队,这会导致在其关联的办公室上进行急切的选择。但是现在二级缓存没有用于我们应该在上一个会话中缓存的办公室。

SELECT team_.Id, team_.Name, team_.OfficeId FROM Team team_ WHERE team_.Id in (7,8,9)

SELECT office_.Id, office_.Name FROM Office office_WHERE office_.Id = 5

为什么会出现 Session #3 中的最后一条 SQL 语句 - 为什么没有使用 2 级缓存,就像在 Session #2 中一样?

【问题讨论】:

  • 您能否提供用于实体的映射?由于缓存过期或内存不足,Office 是否可能在您的第三次会话之前从缓存中删除?此外,NHibernate 的版本可能有助于重现问题。
  • 嗨,谢谢,这是在我的本地计算机上运行的,所以有足够的内存。我正在使用 NH 2.1。缓存过期设置为 20 分钟 - 我已经在 NHibernate 的日志中验证了这一点。映射是使用 Fluent NHibernate 完成的,它们没有什么特别之处。映射包括对 Cache.ReadOnly 或 Cache.NonStrictWrite 的调用。

标签: nhibernate


【解决方案1】:

我已经解决了。

在代码库中,正在使用 Session.CreateSqlQuery().ExecuteUpdate() 进行调用。

但是,它正在执行的查询没有指定实体。当这种情况发生时,NHibernate 似乎决定清除所有缓存区域,清除整个缓存!

故事的寓意,不要在没有指定实体的情况下使用 Session.CreateSqlQuery().ExecuteUpdate()。

【讨论】:

  • 你能在使用 ExecuteUpdate() 时指定一个实体吗?我的理解是,您将 ExecuteUpdate() 用于您特别不希望更新缓存的批次。我很想看看您在使用 ExecueUpdate() 方法时如何保持持久性。
  • 您可能会想到一级缓存。实际上我不知道 - 我在这里的回答是基于我可以通过使用调试器跟踪 NHibernate 源获得的有限理解。我所知道的是,当执行查询时,我的整个二级缓存都被清除了。我将查询更改为使用原始 ADO.NET 命令运行,现在它的表现要好得多。我会尝试找出实际发生的情况,并用更官方的东西更新我的答案。
猜你喜欢
  • 2016-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
相关资源
最近更新 更多