Подтвердить что ты не робот

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(), или я понял что-то совершенно неправильное?

4b9b3361

Ответ 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(), так как он ожидает, что из запроса будет возвращен только один результат.