如何在NHibernate.Linq中缓存.Count()查询

本文关键字:Count 查询 缓存 NHibernate Linq | 更新日期: 2023-09-27 18:25:49

如何缓存这样一个查询的结果:

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

我不能把Cacheable()放在它之后,如果我把它放在Count()之前,它会获取整个结果集,不是吗?

如何在NHibernate.Linq中缓存.Count()查询

在计数之前添加Cacheable将导致缓存聚合计数结果。从下面的例子中生成的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 entity0_.name=@p0;
@p0 = 'Smith' [Type: String (4000)]

可能导致NHibernate忽略Cacheable并返回DB的情况如下:

  1. 会话工厂配置中未启用二级缓存
  2. 实体尚未标记为可缓存

据我所知,唯一会导致NHibernate执行两个SELECT查询的另一种情况是,当实体已从缓存中逐出时,要么显式使用sessionFactory.Evict,要么缓存的实体在两次调用之间过期。