NHibernate - QueryOver Queries
W tym rozdziale zajmiemy się zapytaniami QueryOver. Jest to nowa składnia, która bardziej przypomina LINQ przy użyciu składni łańcucha metod, jak pokazano w poniższym zapytaniu.
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "Laverne");
Nadal jest to kryteria pod osłonami, ale teraz nasze zapytania są silnie wpisywane.
Jak widzieliśmy w zapytaniu kryterialnym, imię jest po prostu nieprzezroczystym ciągiem, teraz używamy w rzeczywistości x.FirstName, więc imię zostanie refaktoryzowane i przemianowane, co zostanie zmienione w zapytaniu kryteriów stylu łącza za pomocą zapytania powyżej.
Nadal możemy zrobić wiele podobnych rzeczy, ale nie możesz używać składni rozumienia zapytań z zapytaniem, musisz użyć składni łańcucha metody i nie możesz łączyć i dopasowywać linku oraz kryteriów.
W przypadku wielu zapytań zapytanie za pośrednictwem interfejsu API jest bardzo przydatne i zapewnia znacznie łatwiejszą do zrozumienia składnię obiektu niż bezpośrednie użycie kryteriów.
Przyjrzyjmy się prostemu przykładowi, w którym pobieramy klienta, którego imię brzmi Laverne, za pomocą zapytania ponad.
using System;
using System.Data;
using System.Linq;
using System.Reflection;
using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Linq;
namespace NHibernateDemo {
internal class Program {
private static void Main() {
var cfg = ConfigureNHibernate();
var sessionFactory = cfg.BuildSessionFactory();
using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction()) {
var customers = session.QueryOver<Customer>()
.Where(x => x.FirstName == "Laverne");
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
tx.Commit();
}
Console.WriteLine("Press <ENTER> to exit...");
Console.ReadLine();
}
private static Configuration ConfigureNHibernate() {
NHibernateProfiler.Initialize();
var cfg = new Configuration();
cfg.DataBaseIntegration(x => {
x.ConnectionStringName = "default";
x.Driver<SqlClientDriver>();
x.Dialect<MsSql2008Dialect>();
x.IsolationLevel = IsolationLevel.RepeatableRead;
x.Timeout = 10;
x.BatchSize = 10;
});
cfg.SessionFactory().GenerateStatistics();
cfg.AddAssembly(Assembly.GetExecutingAssembly());
return cfg;
}
}
}
Jak widać, pod okładkami nadal znajdują się Kryteria, ale jest to po prostu ładniejsza składnia.
Gdy powyższy kod zostanie skompilowany i wykonany, zobaczysz następujące dane wyjściowe.
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
Points: 74
HasGoldStatus: True
MemberSince: 4/4/2009 12:00:00 AM (Utc)
CreditRating: Neutral
AverageRating: 0
Orders:
Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
Press <ENTER> to exit...
Jedną z wad jest to, że powiedzmy, że chcemy to powiedzieć FirstName.StartsWith(“A”) jak pokazano w następującym programie.
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName.StartsWith("A"));
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
tx.Commit();
Teraz uruchommy ponownie aplikację, a zobaczysz, że nie jest to dostawca LINQ, ponieważ nie wie, co to jest StartsWith metoda jest taka, więc otrzymasz plik RunTime exception.
Wyjątek mówi, że nierozpoznane wywołanie metody. Tutaj robimy oczywistą rzecz, ale niekoniecznie działa.
Spróbujmy czegoś innego, na przykład FirstName równa się „A%”, jak pokazano w poniższym kodzie.
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "A%");
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
Uruchommy to jeszcze raz, a zobaczysz, że nie otrzymamy żadnych wyników, jak pokazano poniżej.
Press <ENTER> to exit...
Aby zrozumieć, dlaczego nie uzyskujemy żadnych wyników, spójrzmy na profiler NHibernate.
Jak widać, imię to A%, co nie jest. Znak% jest używany w języku SQL wraz z operatorem like. Teraz musimy utworzyć ograniczenie w klauzuli WHERE, jak pokazano w poniższym programie.
var customers = session.QueryOver<Customer>()
.Where(Restrictions.On<Customer>(c => c.FirstName).IsLike("A%"));
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
Uruchommy ponownie aplikację, a zobaczysz, że wszyscy klienci są pobierani z imionami zaczynającymi się od A.
Alejandrin Will (4ea3aef6-6bce-11e1-b0b4-6cf049ee52be)
Points: 24
HasGoldStatus: False
MemberSince: 10/1/2011 12:00:00 AM (Utc)
CreditRating: VeryVeryGood
AverageRating: 0
Orders:
Order Id: 4ea3aef6-6bce-11e1-b0b5-6cf049ee52be
Austyn Nolan (4ea871b6-6bce-11e1-b110-6cf049ee52be)
Points: 67
HasGoldStatus: True
MemberSince: 12/29/2007 12:00:00 AM (Utc)
CreditRating: Neutral
AverageRating: 0
Orders:
Order Id: 4ea871b6-6bce-11e1-b111-6cf049ee52be
Antonia Murphy (4ea871b6-6bce-11e1-b121-6cf049ee52be)
Points: 72
HasGoldStatus: True
MemberSince: 6/15/2009 12:00:00 AM (Utc)
CreditRating: Terrible
AverageRating: 0
Orders:
Order Id: 4ea871b6-6bce-11e1-b122-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b123-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b124-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b125-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b126-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b127-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b128-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b129-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b12a-6cf049ee52be
Działa tak samo jak wcześniej, z wyjątkiem używania tego nowego QueryOverskładnia. Wielu programistów uważa, że składnia LINQ jest bardziej przystępna i często robi właściwe rzeczy.
Jeśli LINQ nie może sobie z tym poradzić, zaczniesz patrzeć na HQL lub Kryteria, aby sprawdzić, czy to będzie bardziej odpowiednie.
Po prostu daje ci inną składnię, więc Kryteria, zarówno kryteria tworzenia, jak i QueryOver zapewniają kolejny mechanizm zapytań, który pozwala wyciągać dane z bazy danych za pomocą NHibernate.