没有简单的方法可以使您的 LINQ 查询正常工作。您的方案的问题是 NHibernate 不知道如何翻译DateTime.AddHours(double hours)
方法。但是你能用 HQL 写一个类似的查询吗?显然不是。没有标准的 HQL AddHours 函数。因此,您必须注册此新功能。NHibernate 使用方言在 hql 和特定于供应商的 SQL 语法之间进行转换。为此,您必须创建一个派生自现有方言类的新方言类并覆盖 RegisterFunctions 方法。但这仅解决了问题的前半部分。接下来你必须向 NHibernate 展示如何在 LINQ 中使用这个函数。DateTime.AddHours(double hours)
您必须在方法和先前注册的自定义 hql 函数之间“映射” 。NHibernate 为此目的使用了一个注册表。您将不得不扩展默认的 linq-to-hql 注册表。
我将展示一个使用 NHibernate 3.3 的示例
创建一个新的方言类(我的示例使用预定义的 MsSql2008Dialect)
公共类 EnhancedMsSql2008Dialect : MsSql2008Dialect
{
受保护的覆盖无效 RegisterFunctions() {
base.RegisterFunctions();
RegisterFunction("add_hours", new SQLFunctionTemplate(NHibernateUtil.DateTime, "dateadd(hour, ?1, ?2)"));
}
}
创建一个知道如何翻译 AddHours 方法的新 LINQ-to-HQL 生成器类
使用 NHibernate.Linq.Functions;
使用 NHibernate.Linq;
使用 NHibernate.Hql.Ast;
公共类 DateTimeMethodsHqlGenerator : BaseHqlGeneratorForMethod
{
公共 DateTimeMethodsHqlGenerator() {
SupportedMethods = new[] {
ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1))
};
}
公共覆盖 HqlTreeNode BuildHql(System.Reflection.MethodInfo 方法,System.Linq.Expressions.Expression targetObject,System.Collections.ObjectModel.ReadOnlyCollection 参数,HqlTreeBuilder treeBuilder,NHibernate.Linq.Visitors.IHqlExpressionVisitor 访问者){
return treeBuilder.MethodCall("add_hours", visitor.Visit(arguments[0]).AsExpression(), visitor.Visit(targetObject).AsExpression());
}
}
扩展默认的 LINQ-to-HQL 注册表类
公共类 EnhancedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
公共 EnhancedLinqToHqlGeneratorsRegistry() : base() {
//
RegisterGenerator(ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1)), new DateTimeMethodsHqlGenerator());
}
}
配置
cfg.DataBaseIntegration(c => {
c.Dialect<EnhancedMsSql2008Dialect>();
});
cfg.LinqToHqlGeneratorsRegistry<EnhancedLinqToHqlGeneratorsRegistry>();