2013-02-22 18 views
21

Po prostu zacząłem od NHibernate (używając SQLite) w moim bieżącym projekcie i najczęściej używałem Query<>, ponieważ dobrze znałem pisanie zapytań db w Linq.Jaka jest różnica między zapytaniem NHibernate <> a QueryOver <>?

Kiedy stanęła niektórych bardziej złożonych zapytań, zrobiłem rozeznanie na QueryOver<> i zorientowali, że powinna ona być przedkładana nad Query<> ponieważ „składnia QueryOver oznacza NH specyficzny”. Wydaje się również, że nie można nic zrobić, aby Query<> nie mógł tego dokonać.

Więc zacząłem odpowiednio zastępować wszystkie zastosowania Query<>. Nie trwało długo, zanim miałem pierwszy "problem", w którym używanie numeru Query<> wydawało się po prostu wygodniejsze. Przykład (wybierz najwyższą wartość z kolumny w tabeli BillingDataEntityCustomNumber):

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>(); 

Co lubię jest potrzeba jawnie rzutować wynik int i że Query <> wersja jest po prostu łatwiejsze do odczytania. Czy otrzymuję całkowicie błędne zapytanie lub innymi słowy: czy jest lepszy sposób na zrobienie tego?

wziąłem przyjrzeć generowanym wyjściu 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)] 

Co dokładnie patrzę? Czy jest to zapytanie "wewnętrzne" (zależne od metody), które NHibernate dalej tłumaczy na faktyczne zapytanie do bazy danych?

Odpowiedz

26

Istnieje wiele odpowiedzi dotyczących QueryOver kontra Query tutaj na Stackoverflow, ale w skrócie: -

QueryOver jest silnie wpisany wersja Criteria, i jest bardziej NHibernate specyficzny. Prawie wszystko, co możesz zrobić w ICriteria można zrobić z QueryOver. W złotych dniach ICriteria NH2 zawsze miałeś do rzutowania, dlatego właśnie teraz musisz rzucić na końcu łańcucha z powrotem do int.

LINQ (zapytań) jest standardową metodą kwerendy, która działa na IQueryable że nie potrzebuje wyraźnych odniesień do NHibernate i można uznać więcej ORM agnostykiem, a zatem następujący standard linq. Jak słusznie zauważyłeś, nie musisz rzutować na int, ponieważ jesteś wybierając wynik niestandardowy.

Byłbym bardzo zaskoczony twoim prostym przykładem, gdyby wygenerowany SQL był zupełnie inny.

Byłem wielkim fanem QueryOver ale jako dostawcy LINQ jest coraz bardziej dojrzały, a następnie 95% moich zapytań używam Query ale z jakiegoś konkretnego NHibernate rzeczy mi uciekać z powrotem w dół do QueryOver. Tak czy inaczej, polecam użyć narzędzia do profilowania, aby zobaczyć, z czym możesz żyć.

Refs: Tradeoffs lub versus i versus

+0

Nie jestem pewien, czy możesz odpowiedzieć na twoje pierwsze pytanie bezpośrednio, ponieważ moja odpowiedź wskazuje, że QueryOver jest oparty na ICiteria i "to jest sposób, w jaki należy to zrobić, robisz to poprawnie". Aby wyświetlić wygenerowany kod SQL, użyłbym komercyjnego narzędzia, takiego jak NHProf, ponieważ jest ono najlepsze. Nie znaczy być tępym, a HTH wyjaśnia odpowiedź, którą podałem. – Rippo

+0

Dzięki, mają +1 dla niektórych przydatnych informacji. –

+1

Również 'Query ' zwraca 'IQueryable', który jest" IEnumerable ", więc jest super wygodny. – Jess

3

O swojej wersji QueryOver, bym napisał:

int result = Session.QueryOver<BillingDataEntity>() 
       .Select(Projections.Max<BillingDataEntity>(x => x.CustomNumber)) 
       .SingleOrDefault<int>(); 

Wydaje się dość czytelna, a otrzymaną SQL byłoby coś jak:

SELECT max(this_.CustomNumber) as y0_ FROM "BillingDataEntity" this_ 

Mam nadzieję, że pomoże to

Powiązane problemy