LINQプロバイダーと新しいQueryOver構文を使用して、FluentNHibernateとNH3.0で遊んでいます。
QueryOverを使用して、タイムスタンプ値が指定された値にできるだけ近いが、それより大きくないアイテム(結果と呼ばれる)を取得したいと思います。
_ Result precedingOrMatchingResult = Session.QueryOver<Result>().
Where(r => r.TimeStamp < timeStamp).
OrderBy(r => r.TimeStamp).Desc.
FirstOrDefault(); //get the preceding or matching result, if there is any
_
さて、Intellisenseは、FirstOrDefault()
メソッドのようなものはないと言っています。もちろん、注文したクエリを列挙してから、LINQを使用してアイテムを取得することもできます。ただし、これにより、最初にすべてのアイテムがメモリにロードされます。
FirstOrDefault()
に代わるものはありますか、それとも完全に間違っていることを理解しましたか?
NH 3には統合LINQプロバイダーがあります(クエリは内部でHQL/SQLに変換されます)。 NHibernate.Linq名前空間を追加してから、次の操作を行う必要があります。
Result precedingOrMatchingResult = Session.Query<Result>().
Where(r => r.TimeStamp < timeStamp).
OrderByDescending(r => r.TimeStamp).
FirstOrDefault();
IQueryOverインスタンスでTake()拡張メソッドを使用でき、次のようにリストに列挙するだけでよいことがわかりました。
Result precedingOrMatchingResult = Session.QueryOver<Result>().
Where(r => r.TimeStamp < timeStamp).
OrderBy(r => r.TimeStamp).Desc.
Take(1).List(). //enumerate only on element of the sequence!
FirstOrDefault(); //get the preceding or matching result, if there is any
Result precedingOrMatchingResult = Session.QueryOver<Result>()
.Where(r => r.TimeStamp < timeStamp)
.OrderBy(r => r.TimeStamp).Desc
.SingleOrDefault();
試してみてください
Result precedingOrMatchingResult = Session.QueryOver<Result>().
Where(r => r.TimeStamp < timeStamp).
OrderBy(r => r.TimeStamp).Desc.
SetFetchSize(1).
UniqueResult();
UniqueResultは単一の値を返します。値が見つからない場合はnullを返します。これは、FirstまたはDefaultが行うことです。
フェッチサイズを1に設定する必要がある場合と不要な場合がありますが、プロファイラーでテストします。
SetFetchSize(1)
が必要です。 LINQクエリが複数の結果を返す場合、クエリから返される結果は1つだけであると想定しているため、UniqueResult()
を使用してNHibernate例外がスローされます。