NHibernate - DateTime.DayOfYear LINQ

nfp*_*lee 4 c# linq nhibernate

我正在尝试执行以下LINQ查询.

var tasks = session.Query<Task>()
    .Where(t => t.StartDate.DayOfYear == DateTime.UtcNow.DayOfYear)
    .ToList();
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为不支持DayOfYear.但是,如果我说:

var tasks = session.Query<Task>()
    .Where(t => t.StartDate.Day == DateTime.UtcNow.Day)
    .ToList();
Run Code Online (Sandbox Code Playgroud)

它工作正常.所以我决定查看NHibernate源代码,看看他们是如何让它工作的.我在MsSql2000Dialect.cs(MsSql2008Dialect类继承)中找到以下行:

RegisterFunction("day",
    new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(day, ?1)"));
Run Code Online (Sandbox Code Playgroud)

因此,我在构造函数中使用以下行创建了自己的自定义方言(继承自MsSql2008Dialect):

RegisterFunction("dayofyear",
    new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(dy, ?1)"));
Run Code Online (Sandbox Code Playgroud)

然后在我的配置中注册了自定义方言,但我仍然收到以下错误:

NHibernate.QueryException:无法解析属性:DayOfYear

如果有人能告诉我我做错了什么,我会很感激.谢谢

Red*_*eda 8

你完成了一半的工作.

您已经告诉NHibernate如何将HQL dayofyear()方法调用转换为SQL Server方言,但您没有告诉如何将LINQ表达式转换为HQL.基本上你需要扩展LINQ提供程序.我们开始做吧!

首先,我们需要实施一个新的IHqlGeneratorForProperty.只需这样扩展BaseHqlGeneratorForProperty:

public class DateTimeDayOfYearPropertyHqlGenerator : NHibernate.Linq.Functions.BaseHqlGeneratorForProperty
{
    public DateTimeDayOfYearPropertyHqlGenerator()
    {
        SupportedProperties = new[]
            {
                ReflectionHelper.GetProperty((DateTime x) => x.DayOfYear)
            };
    }

    public override NHibernate.Hql.Ast.HqlTreeNode BuildHql(MemberInfo member, Expression expression, NHibernate.Hql.Ast.HqlTreeBuilder treeBuilder, NHibernate.Linq.Visitors.IHqlExpressionVisitor visitor)
    {
        return treeBuilder.MethodCall("dayofyear", visitor.Visit(expression).AsExpression());
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们需要在某个地方注册这个新的发电机.NHibernate使用DefaultLinqToHqlGeneratorsRegistry.让我们扩展这个类:

public class ExtendedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public ExtendedLinqToHqlGeneratorsRegistry()
    {
        this.Merge(new DateTimeDayOfYearPropertyHqlGenerator());
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,我们需要告诉NHibernate使用扩展注册表而不是默认注册表.如果您正在使用Loquacious配置,请执行以下操作:

config.LinqToHqlGeneratorsRegistry<ExtendedLinqToHqlGeneratorsRegistry>();
Run Code Online (Sandbox Code Playgroud)

或者,如果您正在使用FluentNHibernate:

...
.ExposeConfiguration(cfg =>
         cfg.SetProperty(NHibernate.Cfg.Environment.LinqToHqlGeneratorsRegistry,
         typeof(ExtendedLinqToHqlGeneratorsRegistry).AssemblyQualifiedName))
Run Code Online (Sandbox Code Playgroud)

这应该工作了!