No hay manera fácil de hacer su LINQ trabajo de consulta. El problema con su escenario es que NHibernate no sabe cómo traducir el método DateTime.AddHours(double hours)
. ¿Pero puede usar HQL para escribir una consulta similar? Aparentemente no. No hay una función HQL AddHours estándar. Por lo tanto, debe registrar esta nueva función. NHibernate usa dialectos para traducir entre hql y la sintaxis de SQL específica del proveedor. Para hacer esto, debes crear una nueva clase de dialecto derivada de una existente y reemplazar el método RegisterFunctions. Pero esto resuelve solo la primera mitad del problema. A continuación, debe mostrar a NHibernate cómo usar esta función en LINQ. Tiene que "mapear" entre el método DateTime.AddHours(double hours)
y la función hql personalizada previamente registrada. NHibernate usa un registro para este propósito. Deberá extender el registro predeterminado linq-to-hql.
voy a mostrar un ejemplo que trabajó con NHibernate 3.3
Crear una nueva clase dialecto (mi ejemplo se utiliza la predefinido MsSql2008Dialect)
public class EnhancedMsSql2008Dialect : MsSql2008Dialect
{
protected override void RegisterFunctions() {
base.RegisterFunctions();
RegisterFunction("add_hours", new SQLFunctionTemplate(NHibernateUtil.DateTime, "dateadd(hour, ?1, ?2)"));
}
}
crear una nueva clase generador de LINQ a HQL que sabe cómo traducir método AddHours
using NHibernate.Linq.Functions;
using NHibernate.Linq;
using NHibernate.Hql.Ast;
public class DateTimeMethodsHqlGenerator : BaseHqlGeneratorForMethod
{
public DateTimeMethodsHqlGenerator() {
SupportedMethods = new[] {
ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1))
};
}
public override HqlTreeNode BuildHql(System.Reflection.MethodInfo method, System.Linq.Expressions.Expression targetObject, System.Collections.ObjectModel.ReadOnlyCollection arguments, HqlTreeBuilder treeBuilder, NHibernate.Linq.Visitors.IHqlExpressionVisitor visitor) {
return treeBuilder.MethodCall("add_hours", visitor.Visit(arguments[0]).AsExpression(), visitor.Visit(targetObject).AsExpression());
}
}
Extender el defecto LINQ a HQL clase de registro
public class EnhancedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public EnhancedLinqToHqlGeneratorsRegistry() : base() {
//
RegisterGenerator(ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1)), new DateTimeMethodsHqlGenerator());
}
}
Configurar
cfg.DataBaseIntegration(c => {
c.Dialect<EnhancedMsSql2008Dialect>();
});
cfg.LinqToHqlGeneratorsRegistry<EnhancedLinqToHqlGeneratorsRegistry>();
¿Está utilizando NH3.3? y mapeo por código? – Rippo
Sí, uso ambos –