NHibernate - Consultas QueryOver

En este capítulo, cubriremos las consultas QueryOver. Es una nueva sintaxis que se parece más a LINQ usando la sintaxis de cadena de métodos como se muestra en la siguiente consulta.

var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "Laverne");
  • Sigue siendo un criterio oculto, pero ahora nuestras consultas están fuertemente tipadas.

  • Como hemos visto en la consulta de criterios, el primer nombre es solo una cadena opaca, ahora estamos usando un x.FirstName, por lo que el primer nombre se refactoriza y se renombra que se cambia en la consulta de criterios de estilo de enlace usando la consulta over.

  • Todavía podemos hacer muchas cosas similares, pero no puede usar la sintaxis de comprensión de consultas con query over, tiene que usar la sintaxis de la cadena de métodos y no puede mezclar y combinar el enlace y los criterios.

  • Para muchas consultas, la consulta sobre API es muy útil y proporciona una sintaxis de objeto mucho más fácil de comprender que usar Criteria directamente.

Echemos un vistazo a un ejemplo simple en el que recuperaremos un cliente cuyo nombre es Laverne mediante una consulta sobre.

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 puede ver, sigue siendo Criteria debajo de las cubiertas, pero es una sintaxis más agradable.

Cuando se compile y ejecute el código anterior, verá el siguiente resultado.

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...

Una de las desventajas es que, digamos que queremos decir que FirstName.StartsWith(“A”) como se muestra en el siguiente programa.

var customers = session.QueryOver<Customer>() .Where(x => x.FirstName.StartsWith("A"));
 
foreach (var customer in customers.List()) { 
   Console.WriteLine(customer); 
} 

tx.Commit();

Ahora ejecutemos la aplicación nuevamente y verá que este no es un proveedor LINQ ya que no sabe qué StartsWith método es, por lo que obtendrá un RunTime exception.

La excepción dice llamada de método no reconocida. Aquí estamos haciendo lo obvio, pero no necesariamente funciona.

Probemos algo más, como FirstName es igual a "A%" como se muestra en el siguiente código.

var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "A%"); 

foreach (var customer in customers.List()) { 
   Console.WriteLine(customer); 
}

Ejecutemos esto una vez más y verá que no obtendremos ningún resultado como se muestra a continuación.

Press <ENTER> to exit...

Para entender por qué no estamos obteniendo ningún resultado, echemos un vistazo al generador de perfiles de NHibernate.

Como puede ver, el nombre es igual a A% que no lo es. Un% se usa en SQL con el operador like. Ahora necesitamos crear una restricción en la cláusula WHERE como se muestra en el siguiente programa.

var customers = session.QueryOver<Customer>() 
   .Where(Restrictions.On<Customer>(c => c.FirstName).IsLike("A%")); 
	
foreach (var customer in customers.List()) { 
   Console.WriteLine(customer); 
}

Ejecutemos su aplicación nuevamente y verá que todos los clientes se recuperan con el nombre que comienza con 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 de la misma manera que antes, excepto que usa este nuevo QueryOversintaxis. Muchos desarrolladores encuentran que la sintaxis LINQ es más accesible y, a menudo, hace lo correcto.

Si LINQ no puede manejarlo, entonces comenzará a buscar en HQL o Criteria para ver si eso va a ser más adecuado.

Simplemente le brinda una sintaxis diferente, por lo que Criteria, tanto el criterio de creación como el QueryOver le brindan otro mecanismo de consulta que le permite extraer datos de la base de datos usando NHibernate.