В чем разница между запросом NHibernate <> vs QueryOver <>?
Я только что начал с NHibernate (используя SQLite) в моем текущем проекте, и я в основном использовал Query<>
, потому что мне было знакомо писать db-запросы в Linq.
Когда я столкнулся с некоторыми более сложными запросами, я провел некоторое исследование в QueryOver<>
и понял, что он должен быть предпочтительнее Query<>
, потому что "синтаксис QueryOver является специфичным для NH". Кроме того, нет ничего, что Query<>
может сделать, что QueryOver<>
не может выполнить.
Итак, я начал заменять все обычаи Query<>
соответственно. Это было незадолго до того, как у меня появилась первая "проблема", где использование Query<>
казалось просто более удобным.
Пример (выберите наибольшее значение из столбца CustomNumber
в таблице BillingDataEntity
):
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 и что версия Query < > просто легче читать. Я получаю запрос совершенно неправильно или, другими словами: есть ли лучший способ сделать это?
Я посмотрел на сгенерированный вывод 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 далее переводит в фактический запрос к базе данных?
Ответы
Ответ 1
В QueryOver и Query есть много ответов на Stackoverflow, но в двух словах: -
QueryOver - это строго типизированная версия критериев, и это больше NHibernate специфический. Практически все, что вы можете сделать в ICriteria, может выполняться с помощью QueryOver. В золотые дни ICriteria NH2 у вас всегда было чтобы бросить, поэтому именно поэтому вам нужно бросить в конце верните цепочку обратно в int.
LINQ (Query) - это стандартный метод запросов, который работает на IQueryable, что не нуждается в явных ссылках на NHibernate и может быть рассмотрен больше ORM агностик и поэтому следует стандарту linq. Как и ты правильно указал, что вам не нужно бросать в int, поскольку ваши выбрав в результате customNumber.
Я был бы очень удивлен вашим простым примером, если сгенерированный SQL был совсем другим.
Я был большим поклонником QueryOver
, но по мере того, как поставщик Linq становится более зрелым, а 95% моих запросов я использую Query
, но для некоторых конкретных вещей Nhibernate я возвращаюсь обратно к QueryOver
. В любом случае я рекомендую использовать инструмент профилирования, чтобы узнать, с чем вы можете жить.
Refs: Tradeoffs или против и против
Ответ 2
О вашей версии QueryOver я бы написал:
int result = Session.QueryOver<BillingDataEntity>()
.Select(Projections.Max<BillingDataEntity>(x => x.CustomNumber))
.SingleOrDefault<int>();
Кажется вполне читаемым, и получившийся SQL будет примерно таким:
SELECT max(this_.CustomNumber) as y0_ FROM "BillingDataEntity" this_
Надеюсь, это поможет