NHibernate - Consultas QueryOver
Neste capítulo, cobriremos as consultas QueryOver. É uma nova sintaxe que se parece mais com LINQ usando a sintaxe de cadeia de método, conforme mostrado na consulta a seguir.
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "Laverne");
Ainda são critérios ocultos, mas agora nossas consultas são fortemente tipadas.
Como vimos na consulta de critérios, o primeiro nome é apenas uma string opaca, agora estamos realmente usando um x.FirstName, então o primeiro nome é refatorado e renomeado, sendo alterado na consulta de critérios de estilo de link usando a consulta over.
Ainda podemos fazer muitas coisas semelhantes, mas você não pode usar a sintaxe de compreensão de consulta com a consulta over, você tem que usar a sintaxe de cadeia de método e não pode misturar e combinar o link e os critérios.
Para muitas consultas, a consulta sobre API é muito útil e fornece uma compreensão muito mais fácil da sintaxe do objeto do que usar Critérios diretamente.
Vamos dar uma olhada em um exemplo simples no qual recuperaremos um cliente cujo nome é Laverne usando uma consulta over.
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;
}
}
}
Como você pode ver, ainda é Critérios por baixo dos panos, mas é apenas uma sintaxe mais agradável.
Quando o código acima for compilado e executado, você verá a seguinte saída.
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...
Uma das desvantagens é que, digamos que queremos dizer que FirstName.StartsWith(“A”) conforme mostrado no programa a seguir.
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName.StartsWith("A"));
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
tx.Commit();
Agora vamos executar o aplicativo novamente e você verá que este não é um provedor LINQ, pois não sabe o que isso StartsWith método é, então você obterá um RunTime exception.
A exceção diz chamada de método não reconhecida. Aqui estamos fazendo o óbvio, mas não necessariamente funciona.
Vamos tentar outra coisa, como FirstName é igual a “A%” conforme mostrado no código a seguir.
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "A%");
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
Vamos executar isso mais uma vez e você verá que não obteremos nenhum resultado como mostrado abaixo.
Press <ENTER> to exit...
Para entender por que não estamos obtendo nenhum resultado, vamos dar uma olhada no perfilador NHibernate.
Como você pode ver, o primeiro nome é igual a A% que não é. Um% é usado em SQL com o operador like. Agora precisamos criar uma restrição na cláusula WHERE, conforme mostrado no programa a seguir.
var customers = session.QueryOver<Customer>()
.Where(Restrictions.On<Customer>(c => c.FirstName).IsLike("A%"));
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
Vamos executar seu aplicativo novamente e você verá que todos os clientes são recuperados com o primeiro nome começando com 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
Funciona da mesma forma que antes, exceto pelo uso deste novo QueryOversintaxe. Muitos desenvolvedores acham que a sintaxe do LINQ é mais acessível e geralmente faz as coisas certas.
Se o LINQ não puder lidar com isso, você começará a examinar o HQL ou os critérios para ver se isso será mais adequado.
Ele apenas fornece uma sintaxe diferente, então Criteria, ambos os critérios de criação e o QueryOver fornecem a você apenas mais um mecanismo de consulta que permite que você extraia dados do banco de dados usando NHibernate.