1

私のアプリケーションには次のエンティティがあります (製品とモデルの間に多対多の関係があります):

public class TopProduct {
   public virtual int Id { get; set; }
   public virtual Product Product { get; set; }
   public virtual int Order { get; set; }
}

public class Product {
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Model> Models { get; set; }
}

public class Model {
    public virtual string ModelNumber { get; set; }
    public virtual IList<Product> Products { get; set; }
}

注: 製品には数千のモデルが含まれる場合があります。

TopProducts と最初の 5 つのモデル (アルファベット順) のリストをそれぞれに対して表示する必要があります。

たとえば、次のクエリがあるとします。

var topProducts = session.Query<TopProduct>()
    .Cacheable()
    .Fetch(tp => tp.Product).ThenFetchMany(p => p.Models)
    .OrderBy(tp => tp.Order)
    .ToList();

私が今言うなら:

foreach (var topProduct in topProducts) {
    var models = topProduct.Product.Models.Take(5).ToList();

    ...
}

これは、各モデルの第 2 レベルのキャッシュから項目を取得するため、非常にゆっくりと実行されます。製品に対して数千のモデルが存在する可能性があるため、2 回目の実行時にキャッシュから数千のアイテムを取得する必要があります。

これを行うためのより良い方法を考えようと頭を悩ませてきましたが、今のところアイデアがありません。残念ながら、この段階ではモデルとデータベースを変更できません。

助けていただければ幸いです。ありがとう

4

1 に答える 1

0

問題の鍵は、エンティティとクエリのキャッシュがどのように機能するかを理解することです。

エンティティ キャッシュは、基本的に、エンティティの POID とそのプロパティ値を格納します。

インスタンスを取得/初期化する場合、NH は最初にキャッシュをチェックして値が存在するかどうかを確認し、db クエリを回避します。

一方、クエリ キャッシングは、クエリをキー (簡単にするために、コマンド テキストとパラメーター値としましょう) として格納し、エンティティ ID のリストを値として格納します (これは、結果がエンティティのリストであると想定しています)。 、投影ではありません)

NH がキャッシュ可能なクエリを実行すると、結果がキャッシュされているかどうかが確認されます。そうであれば、それらの ID からプロキシをロードします。次に、それらを使用すると、エンティティ キャッシュまたはデータベースから 1 つずつ初期化されます。

コレクションキャッシュも同様です。

通常、これらのエンティティの読み込みに対して多くの第 2 レベルのキャッシュ ヒットを取得することは良いことです。もちろん、別のマシンにある分散キャッシュを使用している場合を除きます。その場合、これはデータベースからそれらを取得するのと同じくらい悪いことです。

その場合は、クエリのキャッシュをスキップすることをお勧めします。

于 2013-05-30T13:23:51.677 に答える