使用二级缓存时,nhibernate查询缓存和实体缓存之间有什么区别? [英] What is the difference between a nhibernate query cache and entity cache when using second level caching?

查看:185
本文介绍了使用二级缓存时,nhibernate查询缓存和实体缓存之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设置nhibernate二级缓存和我在这篇文章中看到,,我想了解查询缓存和实体缓存之间的区别。它说你需要添加

  Cache.ReadOnly();或Cache.ReadWrite(); 
$ / code>

对每一个实体映射都是这样的:

  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');
//通知NHibernate Country实体本身是可缓存的。
Cache.ReadOnly();

code










$ b $ p


$ b

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

是真的需要吗?我是否应该为每一个实体做这件事(不管这个实体多久更换一次?)。如果答案是肯定的,我应该为所有的实体做这个事情,我看到一个页面提到有一个设置实体的风险,因为它可能会导致选择n + 1查询问题,如果您试图将该实体与查询中的其他实体进行连接。我正在使用nhibernate分析器,它看起来像someething只是从下面的代码击中二级缓存。在我的会话设置中,我有以下代码:

$ $ p $ 返回配置
.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();

我有一个通用的Query方法:

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

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

当我使用nhibernate分析器(没有Cache.ReadWrite ()设置在一个实体级别),它似乎仍然打到二级缓存。 (见下面截图)

查询缓存仅存储作为查询返回的实体的标识符。实际的实体存储在实体缓存区域中。因此实体必须配置为可缓存以与查询缓存一起使用。如果使用查询缓存而没有设置可缓存的实体,那么只有查询结果的标识符将被存储在查询缓存中。正如博客所述
lockquote
查询缓存不会缓存
结果集中实际实体的状态;它只缓存标识符值和
类型值的结果。所以查询缓存应该总是和
二级缓存一起使用。

当重新执行相同的查询,NHibernate做的是从查询缓存中获取查询结果中的标识符列表,并且从实体缓存中获取每个实体,如果在缓存中没有找到,则从数据库中查询该元素(最终在多个查询中;每个实体一个) 。因此,总是建议对查询缓存中的实体使用第二级缓存,即您需要指定 Cache.ReadOnly(); 在实体映射中,c $ c>或 Cache.ReadWrite(); 否则查询缓存甚至会通过对一个缓存查询结果进行多个数据库查询来进一步降低应用程序的性能。 p>

I am trying to setup nhibernate second level caching and i see in this article, and i am trying to understand the difference between query caching and entity caching. It says you need to add

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

on every single entity mapping like this:

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

}

But when using nhibernate profiler, i see things hitting the second level cache and I don't have this Cache.ReadOnly() value set.

Is that really required? Should I be doing this for every single entity (no matter how often that entity changes?).

If the answer is yes, that i should be doing this for all entities, I saw a page that mentioned there is a risk of setting an entity with this line as it might lead to Select n + 1 query problem if you are trying to join that entity with other entities in a query. I am using nhibernate profiler and it looks like someething are hitting the second level cache just from the code below. In my session setup, i have the following code:

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

and i have a generic "Query" method that does this:

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

so basically I am trying to confirm if i setup caching correctly as I see some second level cache hits when I using nhibernate profiler but I have not set the Cache in the entity mapping code. I am trying to determine if there are other things i need to do to get caching working (or working better)

When I use nhibernate profiler (without having the Cache.ReadWrite() set at an entity level), it still seems like it does hit the second level cache. (see screenshot below)

解决方案

Query cache only stores the identifiers of entities returned as result of a query. Actual entities are stored in entity cache region. Therefore entity must be configured cacheable to be used with query cache. If query cache is used without setting entities cacheable, still only identifiers of query results will be stored in query cache. As stated in a blog

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.

When re-executing the same query, what NHibernate does is, it gets list of identifiers in query result from query cache, and fetch each entity from entity cache and if not found in cache, queries that element from database (ending up in multiple queries; one for each entity).

Therefore it is always recommended to use 2nd level cache for entities along query cache i.e. you need to specify Cache.ReadOnly(); or Cache.ReadWrite(); in entity mapping else query caching will even further reduce your application performance by making multiple database queries against one cached query result.

这篇关于使用二级缓存时,nhibernate查询缓存和实体缓存之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆