How to cache .Count () requests in NHibernate.Linq?

How to cache the result of such a query:

Session.Query<Entity>().Count(e=> e.Property == someConstant) 

I cannot place Cacheable() after it, and if I put it before Count (), it will retrieve the whole set of results, right?

+4
source share
1 answer

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.

+2
source

Source: https://habr.com/ru/post/1494519/


All Articles