Does NHibernate automatically invalidate query cache entries when second-level cache evictions occur?
0 reputation · 08 Sept 2023, 10:25 UTC
0 reputation · 08 Sept 2023, 10:25 UTC
When using NHibernate’s second‑level cache, developers often enable the query cache to avoid repeated database hits for the same HQL or Criteria queries. The query cache stores results keyed by query string and parameters, and it relies on timestamp information from the underlying tables to decide whether a cached result is still fresh. However, the second‑level cache and the query cache are managed independently; a transaction that updates an entity will increment the timestamp for the second‑level cache region, but the query cache may not be notified of that change unless the table timestamp is also updated.
This independence raises the question of whether NHibernate should automatically purge or invalidate query‑cache entries when a second‑level cache region is evicted or updated, or whether developers must manually coordinate the two caches to avoid serving stale query results.
What mechanism, if any, does NHibernate provide to synchronize query‑cache validity with second‑level cache evictions? Does the current design rely solely on table timestamps, and are there scenarios where those timestamps fail to reflect concurrent updates? Which configuration options or custom listeners can be employed to achieve tighter coupling between the two caches?
26525 reputation · 08 Sept 2023, 15:06 UTC
NHibernate does not automatically delete query‑cache entries when an entity is evicted from the second‑level cache. Instead, it relies on a timestamp‑based mechanism: evicting a second‑level cache entry updates the region’s update timestamp, and the next time the same query is executed NHibernate compares that timestamp with the query‑cache entry’s timestamp to decide whether the entry is stale.
ICache and expose timestamp metadata (e.g., SysCache, Redis, Memcached, InMemory).<cache provider="NHibernate.Caches.SysCache.SysCacheProvider, NHibernate.Caches.SysCache" />).cacheable=true).sessionFactory.Evict(typeof(MyEntity), id) or clear the region).If you are using a custom second‑level cache provider that does not correctly maintain or expose update timestamps, the query cache will not be notified of evictions and stale results could be served. In that case you would need to verify the provider’s timestamp implementation or consider a custom listener that manually removes query‑cache entries on eviction.
Rely on NHibernate’s built‑in timestamp‑based invalidation. Only investigate further if you observe stale query results after a known second‑level cache eviction, in which case you should confirm whether your cache provider correctly updates region timestamps.
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 08 Sept 2023, 20:17 UTC
The query cache does not listen to plain Evict calls on second‑level cache regions. When you call sessionFactory.Evict(typeof(Entity), id) the region’s timestamp is unchanged, so any cached query result that may have returned that entity remains considered fresh. Only an actual update (which increments the region timestamp) or a manual clearing of the query cache (e.g., sessionFactory.EvictQueries()) will cause the query cache to treat the result as stale.