优化NHibernate:加载指定表中的所有数据

时间:2011-11-12 02:51:12

标签: nhibernate caching optimization fluent-nhibernate prefetch

场景:我已经构建了一个管理我的烹饪食谱的ASP.NET MVC应用程序。我使用FluentNHibernate访问下表中的数据:

  1. 用户
  2. 分类
  3. 食谱
  4. RecipeCategories (多对多联结表)
  5. UserBookmarkedRecipes (多对多联结表)
  6. UserCookedRecipes (多对多联结表)
  7. 问题:有没有办法告诉NHibernate从上面列出的所有表中加载所有数据并将其存储在内存/ NHibernate的缓存中,这样就不必再有任何额外的数据库请求了?


    问题背后的动机:多对多关系的多样性构成了一个问题,并且会从优化中受益匪浅。

    有关数据的说明:数据总量非常小。我们现在谈论的食谱不到100个。

1 个答案:

答案 0 :(得分:2)

我建议加载一次,然后在访问时保持它,而不是预加载所有内容。

NHibernate维护着两个不同的缓存,并且可以很好地保持它们与底层数据存储同步。默认情况下,它会在每个会话的基础上使用所谓的“第一级”缓存,但我不认为这是您想要的。您可以在nhibernate faq page on caching

上了解差异

我怀疑你需要二级缓存(这在整个应用程序中都可用)。您需要从NHContrib获取缓存提供程序(下载与您的NHibernate版本匹配的版本)。只要您的应用程序是写入数据库的唯一内容,SysCache2提供程序可能是最容易为您的方案设置的。如果要编写其他进程,则需要确保所有进程都使用相同的缓存作为中介,如果您希望它保持同步。

第二级缓存配置了超时,您可以将其设置为您需要的任何内容。不要认为它可以是无限的,但如果你愿意,你可以将它设置为很长时间(虽然可能不是一个糟糕的想法,但不时回到DB)。如果您想预先加载所有内容,只需从global.asax的Application_Start方法访问所有实体,但这不是必需的。

您需要配置会话工厂以使用缓存。在流畅配置会话工厂时调用.Cache(...)方法,它应该是相对不言自明的。

您还需要在实体映射和关系映射中设置Cache.ReadWrite()。您可以按照惯例或通过在Fluent映射中调用Cache.ReadWrite()来执行此操作。

类似的东西:

public class RecipeMap : ClassMap<Recipe> {
    public RecipeMap () {
        Cache.ReadWrite();
        Id(x => x.Id);
        HasManyToMany(x => x.Ingredients).Cache.ReadWrite();
    }
}

在映射中的Cache调用中,您可以指定ReadOnly或您可能需要的任何其他内容。 NonStrictReadWrite是一个有趣的,它可以显着提高性能,但是从缓存中读取陈旧数据的风险增加。