1

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

  1. 用户
  2. 类别
  3. 食谱
  4. RecipeCategories (多对多连接表)
  5. UserBookmarkedRecipes (多对多联结表)
  6. UserCookedRecipes (多对多连接表)

问题:有什么方法可以告诉 NHibernate 从上面列出的所有表中加载所有数据并将其存储在内存中 / NHibernate 的缓存中,这样就不必有任何额外的数据库请求?


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

数据注意事项:数据总量极少。我们目前谈论的食谱不到 100 种。

4

1 回答 1

2

我建议不要预加载所有内容,而是先加载一次,然后在访问时将其保存。

NHibernate 维护两个不同的缓存,并且在使它们与底层数据存储保持同步方面做得很好。默认情况下,它在每个会话的基础上使用所谓的“一级”缓存,但我认为这不是你想要的。您可以在nhibernate 常见问题解答页面上阅读有关缓存的差异

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

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

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

您还需要在实体映射和关系映射中设置 Cache.ReadWrite()。您可以按照约定或在流利的映射中调用 Cache.ReadWrite() 来执行此操作。

就像是:

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

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

于 2011-11-12T03:04:50.043 回答