Nie ma łatwy sposób dokonać LINQ praca z zapytaniami. Problem ze scenariuszem polega na tym, że NHibernate nie wie, jak przetłumaczyć metodę DateTime.AddHours(double hours)
. Ale czy możesz użyć HQL do napisania podobnego zapytania? Najwyraźniej nie. Nie ma standardowej funkcji HQL AddHours. Dlatego musisz zarejestrować tę nową funkcję. NHibernate używa dialektów do tłumaczenia między składnią SQL a specyficzną dla dostawcy wersją SQL. Aby to zrobić, musisz stworzyć nową klasę dialektów wywodzącą się z istniejącej i zastępującą metodę RegisterFunctions. Ale to rozwiązuje tylko pierwszą połowę problemu. Następnie musisz pokazać NHibernate, jak korzystać z tej funkcji w LINQ. Musisz "mapować" pomiędzy metodą DateTime.AddHours(double hours)
a wcześniej zarejestrowaną niestandardową funkcją hql. NHibernate używa w tym celu rejestru. Będziesz musiał przedłużyć domyślny rejestr linq-to-hql.
pokażę przykład, który pracował z NHibernate 3.3
Utwórz nową klasę dialekt (mój przykład używa predefiniowanego MsSql2008Dialect)
public class EnhancedMsSql2008Dialect : MsSql2008Dialect
{
protected override void RegisterFunctions() {
base.RegisterFunctions();
RegisterFunction("add_hours", new SQLFunctionTemplate(NHibernateUtil.DateTime, "dateadd(hour, ?1, ?2)"));
}
}
Utwórz nowy LINQ-HQL klasy generator, który wie jak przetłumaczyć metodę 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());
}
}
Extend domyślnego LINQ-HQL klasa rejestru
public class EnhancedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public EnhancedLinqToHqlGeneratorsRegistry() : base() {
//
RegisterGenerator(ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1)), new DateTimeMethodsHqlGenerator());
}
}
Konfiguracja
cfg.DataBaseIntegration(c => {
c.Dialect<EnhancedMsSql2008Dialect>();
});
cfg.LinqToHqlGeneratorsRegistry<EnhancedLinqToHqlGeneratorsRegistry>();
Używasz NH3.3? i mapowanie według kodu? – Rippo
Tak, używam obu –