NHibernate Linq提供程序datediff [英] NHibernate linq provider datediff

查看:104
本文介绍了NHibernate Linq提供程序datediff的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是编写类似这样的内容的地方:

Is where a way to write something like this:

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

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

现在我得到一个例外

[NotSupportedException:System.DateTime AddHours(Double)]

[NotSupportedException: System.DateTime AddHours(Double)]

推荐答案

没有简单的方法可以使LINQ查询正常工作.您的方案存在的问题是NHibernate不知道如何转换DateTime.AddHours(double hours)方法.但是,您可以使用HQL编写类似的查询吗?显然不是.没有标准的HQL AddHours函数.因此,您必须注册此新功能. NHibernate使用方言在hql和特定于供应商的SQL语法之间进行翻译.为此,您必须创建一个新的方言类,该类来自现有的方言类,并重写RegisterFunctions方法. 但这只能解决问题的前半部分.接下来,您必须向NHibernate展示如何在LINQ中使用此功能.您必须在DateTime.AddHours(double hours)方法和先前注册的自定义hql函数之间映射". NHibernate为此使用注册表.您将必须扩展默认的linq-to-hql注册表.

There is no easy way to make your LINQ query work. The problem with your scenario is that NHibernate doesn't know how to translate DateTime.AddHours(double hours) method. But can you use HQL to write a similar query? Apparently not. There is no standard HQL AddHours function. Therefore you have to register this new function. NHibernate uses dialects to translate between hql and vendor-specific SQL syntax. In order to do this you have to create a new dialect class deriving from an exising one and override RegisterFunctions method. But this solves only the first half of the problem. Next you have to show NHibernate how to use this function in LINQ. You have to "map" between DateTime.AddHours(double hours) method and the previosly registered custom hql function. NHibernate uses a registry for this purpose. You will have to extend the default linq-to-hql registry.

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

I will show an example that worked with NHibernate 3.3

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

Create a new dialect class (my example uses the predefined MsSql2008Dialect)


    public class EnhancedMsSql2008Dialect : MsSql2008Dialect
    {
        protected override void RegisterFunctions() {
            base.RegisterFunctions();
            RegisterFunction("add_hours", new SQLFunctionTemplate(NHibernateUtil.DateTime, "dateadd(hour, ?1, ?2)"));
        }
    }

创建一个新的LINQ-to-HQL生成器类,该类知道如何转换AddHours方法

Create a new LINQ-to-HQL generator class that knows how to translate AddHours method


    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());
        }
    }

扩展默认的LINQ-to-HQL注册表类

Extend the default LINQ-to-HQL registry class


    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>();

这篇关于NHibernate Linq提供程序datediff的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆