12

SelectまたはSubSelectモードを使用してコレクションを取得するQueryOverを使用してクエリを作成しようとしています。問題のエンティティは です。というコレクションをロードしたいのですが、クエリでこれを実行しています:TrackTrackPrices

q = q.Fetch(item => item.TrackPrices).Eager;

ただし、これによりleft joinが作成され、ページネーションの問題が発生します。別のselectまたはsubselectを実行したいと思います。それができるかどうか、何か考えはありますか?私の知る限り、基準 API を使用すると、次のようになります。

q.DetachedCriteria.SetFetchMode("TrackPrices", FetchMode.Select);

しかし、コード内のマジック ストリングを避けたいので、QueryOver API を使用することをお勧めします。

4

3 に答える 3

3

この質問を投稿してから、他の人にも役立つ回避策/解決策を見つけることができました。

基本的に、このような場合、メイン クエリの主キーを明確に選択する別のクエリを最初に作成し、ページネーションを設定する必要があります。DISTINCT(ID) は必要な結果のみを返すため、SQL のページネーションを問題なく使用できます。次に、ページネーションなしで、ID が返されたリストの 1 つにあるという条件を使用して、メイン クエリを再実行します。条件を受け取り、返された ID を検索し、それらを条件としてメイン条件に追加する一般的なメソッドを作成しました。以下のコード:

public static void LimitCriteriaByPrimaryKeys(this NHibernate.ICriteria criteria, string primaryKeyName, int pageNum, int pageSize)
    {
        var session = NHManager.Instance.GetCurrentSessionFromContext();
        if (pageSize <= 0) pageSize = Int32.MaxValue - 1;
        var nhSession = NHManager.Instance.GetCurrentSessionFromContext();
        var pagingCriteria = (ICriteria)criteria.Clone();
        IList ids = null;
        var pKeyIDName = Projections.Property(primaryKeyName);  
        var pKeyProjection = Projections.Distinct(pKeyIDName); 
        {
            {
                //paging
                pagingCriteria.SetProjection(pKeyProjection); //sets the primary key distinct projection
                if (pageSize > 0)
                {

                    if (pageNum < 1)
                        pageNum = 1;
                    int skipAmt = (pageNum - 1) * pageSize;
                    pagingCriteria.SetFirstResult(skipAmt);
                    pagingCriteria.SetMaxResults(pageSize); 

                    ids = pagingCriteria.List(); //this returns the distinct list of IDs which should be returned for the given page & size

                }
            }
        }
        {
            if (ids != null && ids.Count > 0)
            {
                criteria.Add(Expression.In(pKeyIDName, ids));   //adds the primary key restriction
                var crit = criteria;
                crit.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer());
            }
            else
            {
                criteria.Add(Expression.Eq(pKeyIDName, 0)); //this is added specifically so that the main criteria returns NO results
                criteria.Add(Expression.Eq(pKeyIDName, 1));
            }
        }
    }

メソッドNHManager.Instance.GetCurrentSessionFromContext();を独自のメソッドに置き換えて、セッション ファクトリから現在のセッションを取得できます。

それが役に立てば幸い!

于 2011-05-16T09:43:19.360 に答える
1

ページングと熱心なフェッチを組み合わせるのは難しいです。

Criteria APIを介して選択するフェッチを指定すると、TrackPricesの各アイテムが個別のクエリで読み込まれます-N+1の問題。熱心な読み込みを気にする必要はまったくありません。

N + 1の問題を軽減するために、マッピングでTrackPricesのバッチサイズを設定できます。この記事には、熱心なフェッチとページングの混合に関する詳細がいくつかあります。

于 2011-05-14T17:25:53.127 に答える
1

これはあなたが求めたものではないことはわかっていますが、最悪の場合、ここでさまざまな方法論を使用してタイプ セーフな方法でマジック ストリングをカプセル化できます: C# String enums

于 2011-04-19T16:49:24.240 に答える