Adding caching before counting will result in caching of the results of the aggregate count . This can be seen from the SQL obtained from my example below.
Domain and mapping code
public class Entity { public virtual long id { get; set; } public virtual string name { get; set; } } public class EntityMap : ClassMap<Entity> { public EntityMap() { Id(x => x.id).GeneratedBy.Identity(); Map(x => x.name); Cache.ReadOnly(); } }
The test code itself.
using (var session = NHibernateHelper.OpenSession()) using (var tx = session.BeginTransaction()) { session.Save(new Entity() { name = "Smith" }); session.Save(new Entity() { name = "Smithers" }); session.Save(new Entity() { name = "Smithery" }); session.Save(new Entity() { name = "Smith" }); tx.Commit(); } String name_constant = "Smith"; using (var session = NHibernateHelper.OpenSession()) using (var tx = session.BeginTransaction()) { var result = session.Query<Entity>().Cacheable().Count(e => e.name == name_constant); } using (var session = NHibernateHelper.OpenSession()) using (var tx = session.BeginTransaction()) { var result = session.Query<Entity>().Cacheable().Count(e => e.name == name_constant); }
The SQL generated from the above code can be seen below. As you can see, there are four INSERT , one for each session.Save . While there is only one SELECT , despite two queries, each of which performs a separate session. This is because the count result was cached by NHibernate .
NHibernate: INSERT INTO [Entity] (name) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'Smith' [Type: String (4000)] NHibernate: INSERT INTO [Entity] (name) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'Smithers' [Type: String (4000)] NHibernate: INSERT INTO [Entity] (name) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'Smithery' [Type: String (4000)] NHibernate: INSERT INTO [Entity] (name) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'Smith' [Type: String (4000)] NHibernate: select cast(count(*) as INT) as col_0_0_ from [Entity] entity0_ where entity0_.name=@p0 ; @p0 = 'Smith' [Type: String (4000)]
Possible scenarios that cause NHibernate to ignore Cacheable and return to the database when:
- Layer 2 cache is not included in the factory session configuration.
- The object was not marked as cacheable.
The only other scenario I know about this will cause NHibernate to make two SELECT queries when the object has been cached, either explicitly using sessionFactory.Evict , or after the expiration of the cached object between two calls.
source share