Does NHibernate's second-level cache persist across integration tests when using an in-memory SQLite SessionFactory?
0 reputation · 18 Sept 2023, 03:27 UTC
0 reputation · 18 Sept 2023, 03:27 UTC
When building integration tests for NHibernate, developers often replace the production connection string with an in‑memory SQLite database to avoid credentials while still exercising the full ORM pipeline.
The goal is to determine whether the second‑level cache, if enabled, is automatically cleared between test runs when the same SessionFactory is reused, or whether manual eviction is required to prevent cross‑test contamination.
31775 reputation · 18 Sept 2023, 05:02 UTC
The second-level cache is bound to the SessionFactory, not the Session. When using an in-memory SQLite database, the database data itself is wiped when the connection is closed, but the L2 cache provider (such as Ehcache or a simple in-memory map) remains in memory as long as the SessionFactory instance lives.
SessionFactory for every test, the cache is reset. If you use a singleton factory across tests, the cache persists, potentially leading to cross-test contamination.To prevent data leakage between tests while reusing the SessionFactory, you must manually evict the cache before or after each test. Use the following API calls:
// Clear all entries from the second-level cache
sessionFactory.Cache.Clear();
// Or clear entries for a specific entity type (recommended)
sessionFactory.Cache.EvictEntityData(typeof(MyEntity));
This explanation assumes you are using a standard L2 cache provider configured in your NHibernate settings (e.g., cache.use_second_level_cache). A common point of confusion with SQLite in-memory is that the database itself disappears when the last connection closes. If your test setup closes the database connection between tests, the L2 cache might still contain "keys," but the underlying database data is gone, resulting in cache misses or errors when the next test tries to refresh the cache from the database.
Diagnostic Question: Are you using a single SessionFactory instance for the entire test suite, or are you recreating it for every test method?
Use comments to ask for clarification. Post a solution as an answer.
31,775 reputation · 18 Sept 2023, 14:08 UTC
After each test you can clear the L2 cache with a single line:
sessionFactory.Cache.Clear(); // or EvictAll()
This call is available on NHibernate 5.x+ and removes every entry from all regions, guaranteeing that subsequent Session instances start with a clean slate. If you only want to target a specific entity, sessionFactory.Cache.EvictEntityData(typeof(MyEntity)); is preferable.
SQLite’s in‑memory database is tied to the connection, not the factory. Closing the factory (or disposing the last connection) drops the DB, but the L2 cache stays alive as long as the SessionFactory instance exists. Therefore, re‑using a singleton factory across tests will still leak cached data unless you explicitly evict it or rebuild the factory.