2013-07-31 4 views
4

Как кэшировать результат такого запроса:Как кэшировать запросы .Count() в NHibernate.Linq?

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

Я не могу разместить Cacheable() после него, а если поместить его перед графом(), было бы извлечь весь набор результатов, Wouldnt это?

+0

Посмотрите на метод FromCache() LINQ. –

+0

Где именно должен находиться этот метод? –

+0

Хммм, возможно, вы можете сделать что-то вроде '.Where (e => e.Property == someConstant) .Cacheable(). ToList()', а затем просто используйте свойство .Count' в списке. Или вы конкретно пытаетесь избежать кэширования списка сущностей? – Alden

ответ

2

Добавление кэширования перед подсчетом приведет к кэшированию итоговых результатов подсчета. Это видно из SQL, созданного в моем примере ниже.

домена и картографии Код

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(); 
    } 
} 

сам тестовый код.

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); 
} 

SQL, полученный из приведенного выше кода, приведен ниже. Как вы можете видеть, есть четыре оператора INSERT, по одному для каждого session.Save. В то время как существует только один SELECT, несмотря на два запроса, каждый из которых выполняет отдельную сессию. Это связано с тем, что результат был сфотографирован 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 [email protected]; 
@p0 = 'Smith' [Type: String (4000)] 

Возможные сценарии, которые будут вызывать NHibernate игнорировать Cacheable и вернуться к БД, когда:

  1. Второй тайник уровня не включен в конфигурации сеанса фабрики.
  2. Объект не был помечен как кешируемый.

Единственный сценарий, я знаю, что приведет к NHibernate для выполнения двух SELECT запросов является случаем, когда объект был выселен из кэша, либо явно с помощью sessionFactory.Evict или кэшированный объект становится истек между двумя вызовами.

+0

Отлично, спасибо вам большое! –

+0

@ TomasGrosup рад, что я мог бы помочь! – mickfold

Смежные вопросы