NHibernate 3.0: No FirstOrDefault() with QueryOver?
I am playing with FluentNHibernate and NH 3.0, using the LINQ provider and the new QueryOver syntax.
Now with QueryOver I want to get an item (called result) with a timestamp value as close as possible to a given value, but not greater:
Result precedingOrMatchingResult = Session.QueryOver<Result>().
Where(r => r.TimeSt开发者_C百科amp < timeStamp).
OrderBy(r => r.TimeStamp).Desc.
FirstOrDefault(); //get the preceding or matching result, if there is any
Now, Intellisense tells me that there is no such thing as a FirstOrDefault()
method. I could, of course, enumerate my ordered query, and then use LINQ to get my item. But this would load all items into memory first.
Is there an alternative to FirstOrDefault()
, or have I understood something completely wrong?
I have now found out that I could use the Take() extension method on the IQueryOver instance, and only the enumerate to a list, like so:
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();
NH 3 has an integrated LINQ provider (queries are translated internally to HQL/SQL). You have to add the NHibernate.Linq namespace and then:
Result precedingOrMatchingResult = Session.Query<Result>().
Where(r => r.TimeStamp < timeStamp).
OrderByDescending(r => r.TimeStamp).
FirstOrDefault();
Try
Result precedingOrMatchingResult = Session.QueryOver<Result>().
Where(r => r.TimeStamp < timeStamp).
OrderBy(r => r.TimeStamp).Desc.
SetFetchSize(1).
UniqueResult();
UniqueResult will return a single value, or null if no value is found, which is kinda what First or Default does.
Setting the Fetch Size to 1 may or may not be required, I'd test that with a profiler.
SetFetchSize(1)
is required. If your LINQ query returns more than one result, it will throw an NHibernate exception using UniqueResult()
, as it is only expecting one result to be returned from the query.
精彩评论