4

次の LINQ クエリを実行しようとしています。

var tasks = session.Query<Task>()
    .Where(t => t.StartDate.DayOfYear == DateTime.UtcNow.DayOfYear)
    .ToList();

DayOfYear がサポートされていないため、これは機能しません。しかし、私が言うなら:

var tasks = session.Query<Task>()
    .Where(t => t.StartDate.Day == DateTime.UtcNow.Day)
    .ToList();

それは正常に動作します。そこで、NHibernate のソースを調べて、どのように機能するようになったのかを確認することにしました。MsSql2000Dialect.cs (MsSql2008Dialect クラスが継承するもの) で次の行を見つけました。

RegisterFunction("day",
    new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(day, ?1)"));

したがって、コンストラクターで次の行を使用して、独自のカスタム方言 (MsSql2008Dialect から継承) を作成しました。

RegisterFunction("dayofyear",
    new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(dy, ?1)"));

そして、構成にカスタム方言を登録しましたが、それでも次のエラーが発生します。

NHibernate.QueryException: プロパティを解決できませんでした: DayOfYear

誰かが私が間違っていることを教えてくれれば幸いです。ありがとう

4

2 に答える 2

8

あなたは仕事の半分を終えました。

HQLdayofyear()メソッド呼び出しを SQL Server 方言に変換する方法を NHibernate に指示しましたが、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());
    }
}

次に、この新しいジェネレーターをどこかに登録する必要があります。Hibernate は を使用しDefaultLinqToHqlGeneratorsRegistryます。このクラスを拡張しましょう:

public class ExtendedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public ExtendedLinqToHqlGeneratorsRegistry()
    {
        this.Merge(new DateTimeDayOfYearPropertyHqlGenerator());
    }
}

最後に、デフォルトのレジストリの代わりに拡張レジストリを使用するように NHibernate に指示する必要があります。Loquacious config を使用している場合は、次のようにします。

config.LinqToHqlGeneratorsRegistry<ExtendedLinqToHqlGeneratorsRegistry>();

または、FluentNHibernate を使用している場合:

...
.ExposeConfiguration(cfg =>
         cfg.SetProperty(NHibernate.Cfg.Environment.LinqToHqlGeneratorsRegistry,
         typeof(ExtendedLinqToHqlGeneratorsRegistry).AssemblyQualifiedName))

それは今うまくいくはずです!

于 2013-11-07T13:41:08.660 に答える
0

変数を導入できます:

var dateOfYearUtc= DateTime.UtcNow.DayOfYear;
var tasks = session.Query<Task>()
.Where(t => t.StartDate.DayOfYear == dateOfYearUtc)
.ToList();
于 2013-11-07T12:15:12.063 に答える