NHibernateの最適化:指定されたテーブルからすべてのデータを読み込む

Scenario: I have built an ASP.NET MVC application that manages my cooking recipes. I am using FluentNHibernate to access data from the following tables:

  1. Users
  2. Categories
  3. Recipes
  4. RecipeCategories (many-to-many junction table)
  5. UserBookmarkedRecipes (many-to-many junction table)
  6. UserCookedRecipes (many-to-many junction table)

Question: Is there any way to tell NHibernate to load all data from all tables listed above and store it in memory/in NHibernate's cache so that there do not have to be any additional database requests?


Motivation behind question: The variety of many-to-many relationships poses a problem and would greatly benefit from that optimization.

Note regarding data: The overall amount of data is extremely small. We are talking about less than 100 recipes at the moment.

1
追加された 編集された
ビュー: 1

1 答え

すべてをプリロードするのではなく、一度読み込んでからアクセスしておくことをお勧めします。

NHibernate maintains two different caches, and does a pretty good job of keeping them in sync with your underlying data store. By default, it uses what is called a "first level" cache on a per-session basis but I don't think that's what you want. You can read about the differences at the nhibernate faq page on caching

私は2番目のレベルのキャッシュが必要なものだと思っています(これはアプリ全体で利用可能です)。 NHContrib からキャッシュプロバイダを取得する必要があります(あなたのNHibernateのバージョンと一致します)。 SysCache2プロバイダは、おそらくあなたのアプリケーションがデータベースに書き込むことだけである限り、あなたのシナリオのために設定するのが最も簡単です。他のプロセスが書き込みを行う場合は、すべてのキャッシュが仲介者と同じキャッシュを使用していることを確認して、同期させておく必要があります。

2番目のレベルのキャッシュは、必要なものに設定できるタイムアウトで設定されています。それは無限になるとは思わないが、望むなら長期間に渡って設定することができる(おそらく、時々DBに戻るという恐ろしい考えはない)。全てを事前にロードしたい場合は、global.asaxのApplication_Startメソッドからすべてのエンティティにアクセスできますが、これは必須ではありません。

キャッシュを使用するようにセッションファクトリを構成する必要があります。あなたのセッションファクトリーを流暢に設定するときに.Cache(...)メソッドを呼び出すと、それは比較的自明であるはずです。

また、エンティティマッピングとリレーションシップマッピングの両方でCache.ReadWrite()を設定する必要があります。これは、コンベンションや、流暢なマッピングでCache.ReadWrite()を呼び出すことで行うことができます。

何かのようなもの:

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

マッピングのキャッシュ呼び出しでは、ReadOnlyなど必要なものを指定できます。 NonStrictReadWriteは、パフォーマンスを大幅に向上させることができますが、古いデータをキャッシュから読み取るリスクが高くなります。

2
追加された
あなたの詳細な答えをありがとう、私は本当に努力を感謝します。しかし、私は質問があります:セッションごとに動作する第1レベルキャッシュについてのあなたの記述を理解する限り、このキャッシュ方法は私のシナリオに適していると考えています。 99%の時間は、同時に1人のユーザーしかログインしていません。私のアプリケーションについてもっと知った後でも、NHContrib SysCache2 がより適切だと思っていますか?そうであれば、あなたのアプリケーションの短所は何だと思いますか?最初のレベルのキャッシュ?
追加された 著者 Marius Schulz,
更新:申し訳ありませんが、私はセッションという用語を読み、ASP.NETセッションを考えました。私は今、違いを理解しています、あなたは正しい:その行動は私が達成しようとしているものではありません。
追加された 著者 Marius Schulz,
正確には、私はNHセッションではなく、Webセッションを考えました。私はあなたの答えをできるだけ早く受け入れます!
追加された 著者 Marius Schulz,
これはセッション管理戦略(通常はWebアプリケーションではセッションの存続期間は1回のリクエスト(WebセッションではなくNHセッションと考える))によって異なります。一部のアプリでは、ページ/コントロールごと、またはnhibernateへの呼び出しごとに新しいセッションを取得するだけです。第1レベルのキャッシュは、長寿命ではなく、1つの作業単位内で最適化することを目的としています。そうですね、私は第2レベルがあなたのシナリオにとってまだ適切だと思います。私はSQLiteのような組み込みデータベースを使ってシングルセッションwinformsアプリケーションを使用する場合にのみ、このタイプのキャッシュの第1レベルに頼っています。
追加された 著者 AlexCuse,