8

ページングをサポートするデータを選択するNHibernate基準を作成しています。Ayende Rahienが提案したように、SQL Server 2005(+)の式を使用して、COUNT(*) OVER()使用可能な行の総数を取得しています。合計で何ページあるかを計算できるようにするには、その数が必要です。このソリューションの利点は、行数を取得するために2番目のクエリを実行する必要がないことです。

しかし、私はうまくいく基準を書くことができないようです(AyendeはHQLクエリのみを提供します)。

これが私が欲しいものを示すSQLクエリであり、それはうまく機能します。問題に焦点を合わせるために、実際のページングロジックを意図的に省略していることに注意してください。

SELECT Items.*, COUNT(*) OVER() AS rowcount
FROM Items

HQLは次のとおりです。

select
    item, rowcount()
from 
    Item item

rowcount()関数はカスタムNHibernate方言に登録されCOUNT(*) OVER()、SQLで解決されることに注意してください。

要件は、クエリが基準を使用して表現されることです。残念ながら、私はそれを正しくする方法がわかりません:

var query = Session
    .CreateCriteria<Item>("item")
    .SetProjection(
       Projections.SqlFunction("rowcount", NHibernateUtil.Int32));

私がプロジェクションを追加するときはいつでも、NHibernateはitem(プロジェクションがない場合のように)選択しませんrowcount()が、私が本当に両方を必要としている間だけです。また、全体を投影することはできませんitem。プロパティだけであり、すべてをリストしたくはありません。

誰かがこれに対する解決策を持っていることを願っています。とにかくありがとう。

4

6 に答える 6

5

基準では不可能だと思いますが、いくつかの制限があります。

次のクエリでIDを取得し、アイテムをロードできます。

var query = Session
    .CreateCriteria<Item>("item")
    .SetProjection(Projections.ProjectionList()
       .Add(Projections.SqlFunction("rowcount", NHibernateUtil.Int32))
       .Add(Projections.Id()));

気に入らない場合は、HQLを使用して、結果の最大数を設定することもできます。

IList<Item> result = Session
    .CreateQuery("select item, rowcount() from item where ..." )
    .SetMaxResult(100)
    .List<Item>();
于 2009-11-10T14:08:35.297 に答える
0

なぜCriteriaを使用する必要があるのか​​疑問に思います。session.CreateSQLQueryを使用できませんか?本当に1つのクエリでそれを実行する必要がある場合は、次のように、Itemオブジェクトとカウントをプルバックすることをお勧めします。

select {item.*}, count(*) over() 
from Item {item}

...このようにして、クエリからアイテムオブジェクトをカウントとともに取得できます。Hibernateのキャッシュで問題が発生した場合は、ネイティブクエリに関連付けられたクエリスペース(エンティティ/テーブルキャッシュ)を構成して、古いクエリキャッシュエントリが自動的にクリアされるようにすることもできます。

于 2009-11-02T23:50:07.537 に答える
0

CreateMultiCriteriaを使用します。

この方法でDBに1回ヒットするだけで、2つの単純なステートメントを実行できます。

于 2009-11-01T16:45:34.907 に答える
0

クラスマッピングに数式プロパティを作成します。

<property name="TotalRecords" formula="count(*) over()" type="Int32" not-null="true"/>;

IList<...> result = criteria.SetFirstResult(skip).SetMaxResults(take).List<...>();
totalRecords = (result != null && result.Count > 0) ? result[0].TotalRecords : 0;
return result;
于 2010-04-09T14:56:03.773 に答える
0

私があなたの質問を正しく理解すれば、私は解決策を持っています。私はこれと同じ問題にかなり苦労しました。

同じページにいることを確認するために、私が抱えていた問題について簡単に説明しましょう。私の問題はページングに帰着しました。UIに10個のレコードを表示したいのですが、フィルター基準に一致したレコードの総数も知りたいです。NH基準APIを使用してこれを実現したかったのですが、行数の予測を追加すると、クエリが機能しなくなり、結果が得られませんでした(特定のエラーは覚えていませんが、あなたのように聞こえます)取得しています)。

これが私の解決策です(現在の製品コードからコピーして貼り付けます)。「SessionError」は、IsDev、IsRead、およびIsResolvedの3つのフィルター基準に従って、ページングされたデータを取得するビジネスエンティティの名前であることに注意してください。

ICriteria crit = CurrentSession.CreateCriteria(typeof (SessionError))
    .Add(Restrictions.Eq("WebApp", this));

if (isDev.HasValue)
    crit.Add(Restrictions.Eq("IsDev", isDev.Value));

if (isRead.HasValue)
    crit.Add(Restrictions.Eq("IsRead", isRead.Value));

if (isResolved.HasValue)
    crit.Add(Restrictions.Eq("IsResolved", isResolved.Value));

// Order by most recent
crit.AddOrder(Order.Desc("DateCreated"));

// Copy the ICriteria query to get a row count as well
ICriteria critCount = CriteriaTransformer.Clone(crit)
    .SetProjection(Projections.RowCountInt64());
critCount.Orders.Clear();

// NOW add the paging vars to the original query
crit = crit
    .SetMaxResults(pageSize)
    .SetFirstResult(pageNum_oneBased * pageSize);

// Set up a multi criteria to get your data in a single trip to the database
IMultiCriteria multCrit = CurrentSession.CreateMultiCriteria()
    .Add(crit)
    .Add(critCount);

// Get the results
IList results = multCrit.List();

List<SessionError> sessionErrors = new List<SessionError>();
foreach (SessionError sessErr in ((IList)results[0]))
    sessionErrors.Add(sessErr);

numResults = (long)((IList)results[1])[0];

そこで、オプションの制限付きで基本基準を作成します。次に、それをCLONEし、行数の予測をCLONED基準に追加します。ページング制限を追加するにクローンを作成することに注意してください。次に、元のICriteriaオブジェクトと複製されたICriteriaオブジェクトを含むようにIMultiCriteriaを設定し、IMultiCriteriaを使用して両方を実行します。これで、元のICriteriaからページングされたデータが得られ(必要なデータのみをネットワーク上でドラッグしました)、基準に一致した実際のレコードの数(ページングリンクの表示や作成などに役立ちます)もあります。この戦略は私にとってうまくいきました。これがお役に立てば幸いです。

于 2009-11-10T19:53:08.823 に答える
0

セッションでSetResultTransformer()を呼び出して、カスタム結果トランスフォーマーを調査することをお勧めします。

于 2009-11-18T13:46:56.957 に答える