【问题标题】:How can I load everything up in nhibernate 2nd level cache?如何将所有内容加载到 nhibernate 二级缓存中?
【发布时间】:2014-05-19 03:08:53
【问题描述】:

我有一个使用 nhibernate 和 SQL 服务器的 asp.net-mvc 站点,有一些页面非常慢,因为它们需要视图,需要连接大约 25 个不同表的查询。如果我不是一个大的连接,它需要一段时间,如果我做一个多查询,它似乎仍然需要一段时间

它是一个准备就绪的重型(轻写入)数据库,所以我想看看是否有一种好方法可以将我的数据库的整个对象图(我的服务器有足够的内存)基本上加载到二级缓存中,所以我是确信它很少命中数据库。我正在使用

  NHibernate.Caches.SysCache.SysCacheProvider

作为二级缓存(不是分布式缓存)。这个想法有什么缺陷吗?有推荐的方法吗?

【问题讨论】:

    标签: c# asp.net-mvc caching nhibernate second-level-cache


    【解决方案1】:

    二级缓存总是与会话工厂对象相关联。在运行事务时,它会在会话工厂级别加载对象,以便这些对象可用于整个应用程序,而不是绑定到单个用户。由于对象已经加载到缓存中,因此每当查询返回对象时,此时无需进行数据库事务。

    二级缓存不仅要启用,而且要为您想要缓存的每个单独的实体类进行配置。所以启用缓存映射到 15 个表的所有 15 个对象。

    在 XML 中,这是在元素内部完成的:

    <cache usage="read-write"/>
    

    在 Fluent NHibernate(非自动映射)中,它在 ClassMap 构造函数中或您放置其余映射代码的任何位置完成:

    Cache.ReadWrite().Region("Configuration");
    

    从这里开始取决于数据库的大小和负载,以及新数据必须如何呈现。

    如果 Db 比较小并且写入很少 您可以在每次写入/更新时更新缓存。

    ISession.Clear();
    ReloadCache();
    

    如果 Db 很大: 而且您每天可以奢侈地更新一次数据库,比如说凌晨 12 点,然后将“新”数据在缓存中保存一天,那么您也可以。在重新加载时,您将获得一些用户的延迟峰值。

    这是一个例子: http://www.codeproject.com/Articles/529016/NHibernate-Second-Level-Caching-Implementation

    如果您的数据库很大并且用户必须获取更新的数据,您将不得不手动更新缓存中的数据。

    Database db =   new Database (); 
    Transaction tx = db.BeginTransaction (); 
    try 
    { 
    // Read from the cache 
    MyEntity1 entity1 = cache.Get <MyEntity1> ("pk of entity1"); 
    // Cache is not read from the database 
     if (entity1 ==   null) entity1 = db.Get <MyEntity1> ("pk of entity1"); 
    
    // Entity1 processing 
    
    updated = db.Update, (entity1); / / entity1 update saved to the database 
     if (updated) cache.Put (entity1); / / database update successfully, the update cache 
    
    // Transaction processing 
    
    tx.commit (); 
    } 
    catch 
    { 
    tx.Rollback (); 
    throw; 
    }
    

    更多信息在这里:http://www.databaseskill.com/3093355/

    【讨论】:

    • 我不明白你的代码在做什么。如果您只想将所有实体初始加载到二级缓存中,为什么需要 db.Update
    • 您能否提供有关您的应用程序的更多详细信息,以及读取时数据的“新鲜”程度。上面的代码试图展示你必须更新已经存在于数据库和缓存中的值的场景(基本上这一切都必须手动完成)。
    【解决方案2】:

    您正在缓存您的查询结果,但不是您的实体(这些是单独的缓存) 缓存查询结果只存储 ID;如果您也没有缓存实体,则会发出查询以加载每个返回的实体(这通常很糟糕) MyDTO 类的默认表名是 MyDTO,这就是它要查找的位置 这看起来像一个 Query by ID,您不应该使用松散的命名查询,而是使用适当的加载器 .(see 17.4. Custom SQL for loading) 一旦你设置了加载器和实体缓存,你就可以只使用 session.Get(id) 来检索你的对象,这将使用二级缓存,只要你在事务中完成所有工作,这是推荐的做法。

    【讨论】:

    猜你喜欢
    • 2011-09-02
    • 1970-01-01
    • 2013-12-20
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 2012-11-17
    • 1970-01-01
    相关资源
    最近更新 更多