使用二级缓存时,nhibernate查询缓存和实体缓存有什么区别?

我正在尝试设置nhibernate第二级缓存and i see in this article,,我正在尝试了解查询缓存和实体缓存之间的区别.它说你需要添加

    Cache.ReadOnly();  or Cache.ReadWrite();

在每个单一的实体映射如下所示:

public class CountryMap : ClassMap<country>
{
   public CountryMap()
   {
      Table("dropdowns");
      Id(x => x.Id, "pkey");
       Map(x => x.Name, "ddlong");
      Map(x => x.Code, "dddesc");
       Where("ddtype = 'COUNTRY'");
       //Informing NHibernate that the Country entity itself is cache-able.
       Cache.ReadOnly();
   }

}

但是,当使用nhibernate分析器时,我会看到第二级缓存中的东西,我没有设置这个Cache.ReadOnly()值.

真的需要吗?我应该为每一个实体做这个事情(不管实体变化多久)?

如果答案是肯定的,那么我应该为所有的实体做这个,我看到一个页面提到有一个设置一个这个行的实体的风险,因为它可能导致选择一个查询问题,如果你试图加入实体与查询中的其他实体.我正在使用nhibernate分析器,并且看起来像是从下面的代码中获取第二级缓存.在我的会话设置中,我有以下代码:

  return configuration
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<ApplicationMap>().Conventions.Add(typeof(Conventions)))
            .ExposeConfiguration(
                c => {
                    c.SetProperty("cache.provider_class", "NHibernate.Caches.SysCache.SysCacheProvider, NHibernate.Caches.SysCache");
                    c.SetProperty("cache.use_second_level_cache", "true");
                    c.SetProperty("cache.use_query_cache", "true");
                    c.SetProperty("expiration", "86400");
                })
            .BuildSessionFactory();

我有一个通用的“查询”方法,这样做:

   ICriteria c = Session.CreateCriteria(typeof(T));
   c.SetCacheable(true);
   return c.Future<T>().AsQueryable();

所以基本上我正在尝试确认是否正确设置缓存,因为当我使用nhibernate分析器时我看到一些二级缓存命中,但是我没有在实体映射代码中设置Cache.我试图确定是否还有其他的事情需要做,以缓存工作(或更好的工作)

当我使用nhibernate分析器(没有将Cache.ReadWrite()设置在实体级别)时,似乎仍然会击中第二级缓存. (见下面的屏幕截图)

最佳答案
查询缓存仅存储查询结果返回的实体的标识符.实体实体存储在实体缓存区域中.因此,实体必须配置为可缓存,以便与查询缓存一起使用.如果使用查询缓存而不设置实体可缓存,则只有查询结果的标识符将存储在查询缓存中.如博客中所述

Query cache does not cache the state of the actual entities in the
result set; it caches only identifier values and results of value
type. So the query cache should always be used in conjunction with the
second-level cache.

当重新执行相同的查询时,NHibernate会做什么,它从查询缓存中获取查询结果中的标识符列表,并从实体缓存中获取每个实体,如果没有在缓存中找到,则从数据库中查询该元素(最终在多个查询中;每个实体一个).

因此,始终建议对查询缓存中的实体使用二级缓存,即需要指定Cache.ReadOnly();或Cache.ReadWrite();在实体映射中,查询缓存甚至可以通过针对一个缓存查询结果进行多个数据库查询来进一步降低应用程序性能.

转载注明原文:使用二级缓存时,nhibernate查询缓存和实体缓存有什么区别? - 代码日志