NHibernate 3.0: Нет FirstOrDefault() с QueryOver?
Я играю с FluentNHibernate и NH 3.0, используя поставщик LINQ и новый синтаксис QueryOver.
Теперь с 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()
, или я понял что-то совершенно неправильное?
Ответы
Ответ 1
NH 3 имеет интегрированный поставщик LINQ (запросы транслируются внутренне в HQL/SQL). Вы должны добавить пространство имен NHibernate.Linq, а затем:
Result precedingOrMatchingResult = Session.Query<Result>().
Where(r => r.TimeStamp < timeStamp).
OrderByDescending(r => r.TimeStamp).
FirstOrDefault();
Ответ 2
Теперь я узнал, что я могу использовать метод расширения Take() в экземпляре IQueryOver и только перечислять список, например:
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
Ответ 3
Result precedingOrMatchingResult = Session.QueryOver<Result>()
.Where(r => r.TimeStamp < timeStamp)
.OrderBy(r => r.TimeStamp).Desc
.SingleOrDefault();
Ответ 4
Попробуйте
Result precedingOrMatchingResult = Session.QueryOver<Result>().
Where(r => r.TimeStamp < timeStamp).
OrderBy(r => r.TimeStamp).Desc.
SetFetchSize(1).
UniqueResult();
UniqueResult вернет одно значение, или null, если значение не найдено, которое является чем-то вроде первого или по умолчанию.
Установка размера выборки в 1 может быть или не потребоваться, я бы проверил это с помощью профилировщика.
Ответ 5
SetFetchSize(1)
требуется. Если ваш запрос LINQ возвращает более одного результата, он вызовет исключение NHibernate с помощью UniqueResult()
, так как он ожидает, что из запроса будет возвращен только один результат.