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

Caching 使用二级缓存时,nhibernate查询缓存和实体缓存之间有什么区别?,caching,nhibernate,fluent-nhibernate,Caching,Nhibernate,Fluent Nhibernate,我试图设置nhibernate二级缓存,并试图理解查询缓存和实体缓存之间的区别。它说你需要添加 Cache.ReadOnly(); or Cache.ReadWrite(); 在每个实体映射上,如下所示: public class CountryMap : ClassMap<country> { public CountryMap() { Table("dropdowns"); Id(x => x.Id, "pkey");

我试图设置nhibernate二级缓存,并试图理解查询缓存和实体缓存之间的区别。它说你需要添加

    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();
   }
// xml
<class name="Country" ...>
  <cache usage="read-write" region="ShortTerm" include="non-lazy/all"/>

// fluent
public CountryMap()
{
    Cache.IncludeAll() // or .IncludeNonLazy
        .Region("regionName")
        .NonStrictReadWrite();
公共类CountryMap:ClassMap
{
公共国家地图()
{
表(“下拉列表”);
Id(x=>x.Id,“pkey”);
Map(x=>x.Name,“ddlong”);
地图(x=>x.代码,“dddesc”);
其中(“ddtype=‘国家’”);
//通知NHibernate国家实体本身是可缓存的。
Cache.ReadOnly();
}
}

但是当使用nhibernate探查器时,我看到一些东西进入了二级缓存,而我没有设置这个cache.ReadOnly()值

真的需要吗?我是否应该为每个实体都这样做(无论该实体更改的频率如何?)

如果答案是肯定的,那么我应该对所有实体执行此操作,我看到一个页面,其中提到了使用此行设置实体的风险,因为如果您尝试将该实体与查询中的其他实体联接,则可能会导致选择n+1查询问题。我使用的是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();
返回配置
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf().Conventions.Add(typeof(Conventions)))
.曝光配置(
c=>{
c、 SetProperty(“cache.provider_class”,“NHibernate.Caches.SysCache.SysCacheProvider,NHibernate.Caches.SysCache”);
c、 SetProperty(“缓存。使用二级缓存”,“true”);
c、 SetProperty(“cache.use_query_cache”,“true”);
c、 SetProperty(“到期日”、“86400”);
})
.BuildSessionFactory();
我有一个通用的“查询”方法可以做到这一点:

   ICriteria c = Session.CreateCriteria(typeof(T));
   c.SetCacheable(true);
   return c.Future<T>().AsQueryable();
ICriteria c=Session.CreateCriteria(typeof(T));
c、 可设置缓存(true);
返回c.Future().AsQueryable();
因此,基本上,我正在尝试确认是否正确设置了缓存,因为我在使用nhibernate profiler时看到一些二级缓存命中,但我没有在实体映射代码中设置缓存。我正在尝试确定是否需要做其他事情才能使缓存工作(或更好地工作)

当我使用nhibernate探查器时(没有在实体级别设置Cache.ReadWrite()),它似乎仍然命中了第二级缓存。(见下面的屏幕截图)


是的,您必须对所有实体执行此操作。但是,这可以通过xml配置而不是映射来完成:

我想提供一些关于NHibernate中的(第二级)缓存选项的总结。首先,有4种设置。事实上,这些确实代表了非常精细的缓存设置的真正威力

  • -全局开关
  • -全局开关
  • -类/实例级别
  • .SetCacheable(true).SetCacheMode(CacheMode.Normal).SetCacheRegion(“yyy”)
    -每个查询
  • 前两个是全局使能/禁用因素。必须先打开它们,然后才能使用下一个/最后两个设置

    但事实上,答案已经存在。全局方法-支持缓存,局部方法-决定1)如何处理,2)处理哪个类/查询-如果愿意或根本不

    例如,这是的一个片段:

    让我明确指出以下评论:

    如果启用了二级缓存,则需要缓存提供程序
    或已启用查询缓存请注意,默认情况下启用useSecondLevelCache

    (注意:还可以看到第一个
    PropertiesHelper.GetBoolean()
    调用传递最后一个默认值
    true

    这意味着,如果3。设置(
    )并不重要。。。所有映射的实例都将被缓存。。。非托管,默认方式

    幸运的是,这不是真的。三。班级层面的设置很重要。这是必须的。没有这样的显式设置:

    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();
       }
    
    // xml
    <class name="Country" ...>
      <cache usage="read-write" region="ShortTerm" include="non-lazy/all"/>
    
    // fluent
    public CountryMap()
    {
        Cache.IncludeAll() // or .IncludeNonLazy
            .Region("regionName")
            .NonStrictReadWrite();
    
    最后,我们应该在这里提到4。选项(查询级别
    。可设置缓存(true)
    )应与二级缓存一起提供:

    查询结果集也可以缓存。这仅适用于经常使用相同参数运行的查询。要使用查询缓存,必须首先启用它:

    )和2)它是可配置的。事实上,我们可以使用不同的并发策略、区域、延迟加载处理。。。或者甚至不使用它们。。。这是必要的。有些实体“几乎是只读的”(例如国家代码列表),而有些实体变化很大


    我们能做的最好的就是和他一起玩。试验。最后,我们可以拥有性能良好的机器。

    查询缓存只存储查询结果返回的实体的标识符。实际实体存储在实体缓存区域中。因此,实体必须配置为可缓存,以便与查询缓存一起使用。如果使用查询缓存时未设置实体可缓存,则仍然只有查询结果的标识符将存储在查询缓存中。正如在博客中所说的那样

    查询缓存不缓存数据库中实际实体的状态 结果集;它只缓存标识符值和值的结果 类型。因此,查询缓存应始终与 二级缓存

    当重新执行同一查询时,NHibernate所做的是,它从查询缓存中获取查询结果中的标识符列表,并从实体缓存中获取每个实体,如果在缓存中找不到,则从数据库中查询该元素(以多个查询结束;每个实体一个查询)

    因此,始终建议
    <add key="hibernate.cache.use_query_cache" value="true" />