2

目標は、NHibernateとLinqを使用して次のようなことを行うことです。

Session.Query<MyClass>().Where(x => x.DateGreaterThen(DateTime.Now))

この例は少し単純化されていますが、Wh​​ere述語でMyClassメソッドを呼び出したいという考え方です。したがって、MyClassは次のようになります。

public class MyClass
{
    public static readonly Expression<Func<MyClass, DateTime, bool>> GreaterThenExpression =
        (x, dt) => x.MyDateTimeProperty > dt.Date;

    private static readonly Func<MyClass, DateTime, bool> GreaterThenFunc = GreaterThenExpression.Compile();

    public Guid Id { get; set; }

    public DateTime MyDateTimeProperty { get; set; }

    public bool DateGreaterThen(DateTime dt)
    {
        return GreaterThenFunc(this, dt);
    }
}

カスタムジェネレーター:

public class EntityMethodGenerator<T1, T2, TResult> : BaseHqlGeneratorForMethod
{
    private Expression<Func<T1, T2, TResult>>  _returnValueExpression;

    public EntityMethodGenerator()
    {
        SupportedMethods = new[]
                               {
                                   ReflectionHelper.GetMethodDefinition<MyClass>(myClass => myClass.DateGreaterThen(DateTime.Now))
                               };
    }

    public static void Register(ILinqToHqlGeneratorsRegistry registry, Expression<Action<T1>> method, Expression<Func<T1, T2, TResult>> returnValueExpression)
    {
        var generator = new EntityMethodGenerator<T1, T2, TResult> { _returnValueExpression = returnValueExpression };

        registry.RegisterGenerator(ReflectionHelper.GetMethodDefinition(method), generator);
    }

    public override HqlTreeNode BuildHql(
        MethodInfo method,
        Expression targetObject,
        ReadOnlyCollection<Expression> arguments,
        HqlTreeBuilder treeBuilder,
        IHqlExpressionVisitor visitor)
    {
        return visitor.Visit(_returnValueExpression);
    }
}

そして最後に、カスタムカスタムジェネレータレジストリ:

public class OwnLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public OwnLinqToHqlGeneratorsRegistry()
    {
        EntityMethodGenerator<MyClass, DateTime, bool>.Register(this, (myClass) => myClass.DateGreaterThen(DateTime.Now), MyClass.GreaterThenExpression);
    }   
}

しかし、これは機能していませSystem.Data.SqlClient.SqlException : Invalid column name 'dt'.ん。BuildHqlメソッドが正しく実装されていないのではないかと疑っています。これを修正するのに役立ちますか?

ちなみに、メソッドGreaterThenExpressionでHqlTreeを手動で構築するのではなく、ジェネレーターで式を使用したいと思います。BuildHql

4

1 に答える 1

1

GreaterThenExpression はランバです。BuildHql() では、targetObject と引数にも注意する必要があります。そうしないと、適用されていないラムダの HQL 変換を HQL ツリーに挿入することになります。

ラムダの本体を抽出し、そのパラメーターを targetObject と引数に置き換える必要があります。次に、それから HQL を生成できます。Remotion.Linq.Parsing.ExpressionTreeVisitors.MultiReplaceingExpressionTreeVisitor を使用してみてください。

(ちなみに、GreaterThen ではなく、GreaterThan にする必要があります。)

于 2013-01-29T13:07:11.707 に答える