2013-02-22 22 views
21

私は現在のプロジェクトでNHibernate(SQLiteを使用しています)を使い始めました。私はLinqでdbクエリを書いていたので、たいていQuery<>を使用しました。私はいくつかのより複雑なクエリに直面した時NHibernate Query <>とQueryOver <>の違いは何ですか?

、私はQueryOver<>上のいくつかの研究を行なったし、「QueryOver構文は、特定のNHである」ので、それはQuery<>よりも優先されるべきであることを考え出しました。また、が行うことができるものはありません。QueryOver<>は達成できません。

私はそれに応じてQuery<>のすべての使用を置き換え始めました。私が最初の「問題」を持ってから、Query<>を使ったほうがはるかに便利だったのはずっと前です。 例(表BillingDataEntityの列CustomNumberから最高値を選択するには):私が嫌いする必要がある

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型に結果をキャストすると、クエリ<>バージョンが読みちょうどより簡単であること。クエリが完全に間違っている、つまり言い換えれば、それを行うより良い方法はありますか?

私は、生成された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が実際のデータベースクエリにさらに変換する "内部"(メソッド依存)クエリですか?

答えて

26

StackOverflowのではなく、一言で言えば、ここでのクエリに対してQueryOverに関する答えがたくさんあります: -

QueryOverは、基準の厳密に型指定されたバージョンであり、そしてより多くの NHibernateは固有のものです。 ICriteriaで行うことができるものは、 のQueryOverで行うことができます。 ICriteria NH2の黄金時代には、常にキャストするために を持っていたので、今は のチェーンの最後にキャストしてintにキャストする必要があります。

LINQ(クエリ) はNHibernateのに明示的な参照を必要とせず、 よりORMとらわれないと考えられ、したがって、LINQの標準に従ってできることのIQueryable上で動作標準クエリ方法です。 が指摘しているように、intにキャストする必要はありません。 結果にcustomNumberを選択します。

生成されたSQLが非常に異なる場合、私はあなたの単純な例で非常に驚くでしょう。

私はQueryOverの大ファンだったが、LINQのプロバイダはその後、私のクエリの95%を、より成熟してきているように私はQueryを使用しますが、いくつかのNHibernateは、特定のもののために私はQueryOverまで戻って訴えます。いずれにしても、プロファイリングツールを使用して、あなたが住んでいるものを見ることをお勧めします。

参考文献:あなたのQueryOverバージョンについてTradeoffsまたはversusversus

+0

私はあなたの最初の質問に直接答えることはできませんが、私の答えは、ICOに基づいてQueryOverが指摘しているように、「これはあなたが正しくやっているということです。生成されたSQLを表示するには、NHProfのような商用ツールを使用するのが最良です。鈍い意味ではなく、HTHは私が与えた答えを明らかにする。 – Rippo

+0

ありがとう、いくつかの有用な情報のために+1してください。 –

+1

また、 'クエリ'は 'IEnumerable'である' IQueryable'を返しますので、非常に便利です。 – Jess

3

、私が書かれています:

int result = Session.QueryOver<BillingDataEntity>() 
       .Select(Projections.Max<BillingDataEntity>(x => x.CustomNumber)) 
       .SingleOrDefault<int>(); 

をそれは非常に読みやすいようで、結果のSQLは次のようなものになるだろう:

SELECT max(this_.CustomNumber) as y0_ FROM "BillingDataEntity" this_ 

希望すると便利です。

関連する問題