NHibernate linq提供程序datediff

NHibernate linq提供程序datediff,linq,nhibernate,Linq,Nhibernate,这是一种写这样东西的方式: public class Item { public DateTime Start { get; set; } public DateTime Finish{ get; set; } } Sessin.Query<Item>.Where( x => x.Start.AddHours( 3 ) > x.Finish ); 公共类项目 { 公共日期时间开始{get;set;} 公共日期时间完成{get;set;} } sessi

这是一种写这样东西的方式:

public class Item
{
    public DateTime Start { get; set; }
    public DateTime Finish{ get; set; }
}

Sessin.Query<Item>.Where( x => x.Start.AddHours( 3 ) > x.Finish );
公共类项目
{
公共日期时间开始{get;set;}
公共日期时间完成{get;set;}
}
session.Query.Where(x=>x.Start.AddHours(3)>x.Finish);
现在我有一个例外

[NotSupportedException:System.DateTime添加小时数(双倍)]


如果您使用的是NH3.3和饶舌的配置,那么您可以这样做

LinqToHqlGeneratorsRegistry
添加到配置中:-

        var configure = new Configuration()
            .DataBaseIntegration(x => {
                x.Dialect<CustomDialect>();
                x.ConnectionStringName = "db";
             })
            .LinqToHqlGeneratorsRegistry<MyLinqtoHqlGeneratorsRegistry()
            .CurrentSessionContext<WebSessionContext>();
var configure=新配置()
.数据库集成(x=>{
x、 方言();
x、 ConnectionStringName=“db”;
})
.linqtohql生成器注册表
d、 Value.AddHours((双精度)0)
};
}
公共重写HqlTreeNode BuildHql(MethodInfo方法,
System.Linq.Expressions.Expression targetObject,
只读集合参数,
HqlTreeBuilder treeBuilder、IHqlExpressionVisitor(访客)
{
返回treeBuilder.MethodCall(“AddHours”,
visitor.Visit(targetObject).AsExpression(),
visitor.Visit(参数[0]).AsExpression()
);
}
}
公共类自定义方言:MSSQLS008方言
{
公共方言()
{
注册函数(
“增加小时数”,
新的SQLFunctionTemplate(
NHibernateUtil.DateTime,
“日期添加(hh,?2,?1)”
)
);
}
}
我是基于法比奥的这个

您现在可以按原样使用代码:-

Session.Query<Item>.Where( x => x.Start.AddHours( 3 ) > x.Finish );
Session.Query.Where(x=>x.Start.AddHours(3)>x.Finish);

这在3.2中也是可能的,但是
公共覆盖HqlTreeNode BuildHql(..)
参数略有不同…

要使LINQ查询工作起来并不容易。您的场景的问题是NHibernate不知道如何翻译
DateTime.AddHours(双小时)
方法。但是您可以使用HQL编写类似的查询吗?显然不是。没有标准的HQL AddHours函数。因此,您必须注册这个新函数。NHibernate使用方言在hql和特定于供应商的SQL语法之间进行转换。为了做到这一点,您必须创建一个从现有方言类派生的新方言类,并重写RegisterFunctions方法。 但这只解决了问题的前一半。接下来,您必须向NHibernate演示如何在LINQ中使用此函数。您必须在
DateTime.AddHours(双小时)
方法和先前注册的自定义hql函数之间进行“映射”。NHibernate为此目的使用注册表。您必须将默认linq扩展到hql注册表

我将展示一个使用NHibernate 3.3的示例

创建一个新的方言类(我的示例使用预定义的MSSQLS2008方言)

公共类增强器DMSql2008方言:MSSql2008方言 { 受保护的覆盖无效注册表函数(){ base.RegisterFunctions(); RegisterFunction(“添加小时”,新的SQLFunctionTemplate(NHibernateUtil.DateTime,“日期添加(小时,1,2)”); } } 创建一个新的LINQ到HQL生成器类,该类知道如何转换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()); } } 使用NHibernate.Linq.Functions; 使用NHibernate.Linq; 使用NHibernate.Hql.Ast; 公共类DateTimeMethodsHqlGenerator:BaseHqlGeneratorFormMethod { public DateTimeMethodsHqlGenerator(){ SupportedMethods=new[]{ ReflectionHelper.GetMethodDefinition((日期时间x)=>x.AddHours(1)) }; } 公共重写HqlTreeNode BuildHql(System.Reflection.MethodInfo方法,System.Linq.Expressions.Expression targetObject,System.Collections.ObjectModel.ReadOnlyCollection参数,HqlTreeBuilder treeBuilder,NHibernate.Linq.Visitors.IHqlExpressionVisitor){ 返回treeBuilder.MethodCall(“add_hours”,visitor.Visit(参数[0]).AsExpression(),visitor.Visit(targetObject.AsExpression()); } } 将默认LINQ扩展到HQL注册表类

public class EnhancedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry { public EnhancedLinqToHqlGeneratorsRegistry() : base() { // RegisterGenerator(ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1)), new DateTimeMethodsHqlGenerator()); } } 公共类增强InQTOhQlGeneratorsRegistry:DefaultLinqToHqlGeneratorsRegistry { 公共增强InqToHqlGeneratorsRegistry():base(){ // RegisterGenerator(ReflectionHelper.GetMethodDefinition((DateTime x)=>x.AddHours(1)),新的DateTimeMethodsHqlGenerator(); } } 配置

cfg.DataBaseIntegration(c => { c.Dialect<EnhancedMsSql2008Dialect>(); }); cfg.LinqToHqlGeneratorsRegistry<EnhancedLinqToHqlGeneratorsRegistry>(); 数据库集成(c=>{ c、 方言(); }); LinqToHqlGeneratorsRegistry();
你用的是NH3.3吗?代码映射?与我的答案基本相同,五分钟后回答:)在编辑时没有按“显示新答案”,留下了我的解决方案,因为您的解决方案在编辑之前没有自定义方言谢谢您的答案和对情况的良好描述。顺便说一句,在DefaultLinqToHqlGeneratorsRegistry中使用合并方法看起来更漂亮:)谢谢您的解决方案!很抱歉,我接受了另一个答案,因为它很好地描述了发生的事情和原因。别担心,我不太在意,虽然我有一点觉得另一个答案应该删除,但你赢了一些,你输了一些。不确定你问的是什么,datetime减去两个日期吗?如果只有小时数,则使用
AddHours(-4)
public class EnhancedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry { public EnhancedLinqToHqlGeneratorsRegistry() : base() { // RegisterGenerator(ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1)), new DateTimeMethodsHqlGenerator()); } } cfg.DataBaseIntegration(c => { c.Dialect<EnhancedMsSql2008Dialect>(); }); cfg.LinqToHqlGeneratorsRegistry<EnhancedLinqToHqlGeneratorsRegistry>();