私は現在のプロジェクトで(SQLiteを使用して)NHibernateを開始しましたが、ほとんどQuery<>
を使用していました。
より複雑なクエリに直面したとき、QueryOver<>
でいくつかの研究を行い、「QueryOver構文はNH固有」であるため、Query<>
よりも優先されるべきだと考えました。また、Query<>
ができないこと、QueryOver<>
が達成できないことは何もないようです。
そこで、Query<>
のすべての使用法をそれに応じて置き換え始めました。 Query<>
を使用するほうが便利だと思われる最初の「問題」が発生するのはそう長くはありませんでした。例(テーブルCustomNumber
の列BillingDataEntity
から最大値を選択):
int result = Session.Query<BillingDataEntity>().Select(x => x.CustomNumber).OrderByDescending(a => a).FirstOrDefault();
int result = Session.QueryOver<BillingDataEntity>().Select(x => x.CustomNumber).OrderBy(a => a.CustomNumber).Desc.Take(1).SingleOrDefault<int>();
私が嫌いなのは、結果を明示的にintにキャストする必要があることと、Query <>バージョンの方が読みやすいことです。クエリが完全に間違っていますか、言い換えれば、それを行うより良い方法はありますか?
生成されたSQL出力を確認しました。
NHibernate: select billingdat0_.CustomNumber as col_0_0_ from "BillingDataEntity" billingdat0_ order by billingdat0_.CustomNumber desc limit 1
NHibernate: SELECT this_.CustomNumber as y0_ FROM "BillingDataEntity" this_ ORDER BY this_.CustomNumber desc limit @p0;@p0 = 1 [Type: Int32 (0)]
正確には何を見ていますか?これは、NHibernateがさらに実際のデータベースクエリに変換する「内部」(メソッド依存)クエリですか?
StackOverflowでは、簡単に言えば、QueryOverとQueryについての回答がたくさんあります。
QueryOverはCriteriaの厳密に型指定されたバージョンであり、NHibernate固有のものです。 ICriteriaでできることのほとんどは、QueryOverで実行できます。 ICriteria NH2の黄金時代には、常にキャストする必要がありました。そのため、チェーンの最後にキャストしてintに戻す必要があります。
LINQ(クエリ)は、NHibernateへの明示的な参照を必要としないIQueryableで機能する標準クエリメソッドであり、よりORMに依存しないと見なされるため、linq標準に従います。正しく指摘したように、結果にcustomNumberを選択しているので、intにキャストする必要はありません。
生成されたSQLが非常に異なる場合、単純な例に非常に驚かされます。
私はQueryOver
の大ファンでしたが、Linqプロバイダーが95%のクエリよりも成熟しているので、Query
を使用しますが、Nhibernate固有のものにはQueryOver
。いずれにせよ、プロファイリングツールを使用して、何に対応できるかを確認することをお勧めします。
QueryOverのバージョンについては、次のように記述します。
int result = Session.QueryOver<BillingDataEntity>()
.Select(Projections.Max<BillingDataEntity>(x => x.CustomNumber))
.SingleOrDefault<int>();
とても読みやすいようで、結果のSQLは次のようになります。
SELECT max(this_.CustomNumber) as y0_ FROM "BillingDataEntity" this_
これが役立つことを願っています