3

我正在尝试为限制 DateTime 制定扩展方法?财产。它用于搜索查询,我真的不想为所有可能的日期字段复制此代码。

public static IQueryOver<T, T> WhereInOpenEndedDateRange<T>(this IQueryOver<T, T> query, 
    Expression<Func<object>> field, 
    DateTime? rangeFrom, 
    DateTime? rangeTo)
{
    if(rangeFrom.HasValue && rangeTo.HasValue)
    {
        query.WhereRestrictionOn(field).IsBetween(rangeFrom.Value).And(rangeTo.Value);
    }
    else if (rangeFrom.HasValue)
    {
        //query.Where(() => /* help */ >= rangeFrom.Value);
    }
    else if (rangeTo.HasValue)
    {
        //query.Where(() => /* help */ <= rangeTo.Value);
    }

    return query;
}

我认为我缺少表达的基本方面。是否可以传递某种形式的表达式参数并在现场使用它/* help */

谢谢

更新

越来越近了,但还是觉得好远……

else if (rangeFrom.HasValue)
{
    var lt = Expression.LessThanOrEqual(field, Expression.Constant(rangeFrom, typeof(DateTime?)));
    var b = Expression.Lambda<Func<bool>>(lt);
    query.Where(b);
}

但这将不起作用,因为它会Func<object>DateTime?. 如何将原始属性表达式合并为新的Func<bool>并保留所需的位以保持 NH QueryOver 的完整?

在查看 QueryOverRestrictionBuilder 的 NH 源之后,我会做

string propertyName = ExpressionProcessor.FindMemberExpression(field.Body)

并使用 Criteria 方法构建限制。

4

1 回答 1

2

好吧,我不知道如何使用

Expression<Func<bool>> 

签名,但这仅适用于 DateTime?s ,所以我看不出我添加的限制会有什么不同。

基本上,您需要表达式(示例中的字段)与您发送的参数完全匹配,即 x=>x.SomeNullableDateField。'x' 是您开始使用的查询类型

session.QueryOver<YourClass>()

所以它需要包含在发送的表达式类型中。你也错过了获取该参数,使用

ParameterExpression param = expression.Parameters.Single() 

用于构造比较表达式。

您正在将 BinaryExpression 转换为Expression<Func<bool>>,但您必须更进一步将其转换为Expression<Func<T, bool>>.

public static IQueryOver<T, T> WhereInOpenEndedDateRange<T>(this IQueryOver<T, T> query,
    Expression<Func<T, DateTime?>> expression,
    DateTime? rangeFrom,
    DateTime? rangeTo) where T : class
{
    // Lambda being sent in
    ParameterExpression param = expression.Parameters.Single();

    if(rangeFrom.HasValue && rangeTo.HasValue)
    {
        // GT Comparison
        var expressionGT =
            Expression.GreaterThanOrEqual(
                expression.Body,
                Expression.Constant(rangeFrom.Value, typeof(DateTime?)
            )
        );

        // LT Comparison
        var expressionLT =
            Expression.LessThanOrEqual(
                expression.Body,
                Expression.Constant(rangeTo.Value, typeof(DateTime?)
            )
        );

        query.Where(
               Expression.Lambda<Func<T, bool>>(expressionGT, param))
               .And(
               Expression.Lambda<Func<T, bool>>(expressionLT, param)
        );
    }
    else if(rangeFrom.HasValue)
    {
        // GT Comparison
        BinaryExpression expressionGT =
            Expression.GreaterThanOrEqual(
                expression.Body,
                Expression.Constant(rangeFrom.Value, typeof(DateTime?)
            )
        );

        // covert to lambda
        query.Where(Expression.Lambda<Func<T, bool>>(expressionGT, param));
    }
    else if(rangeTo.HasValue)
    {
        // LT Comparison
        BinaryExpression expressionLT =
            Expression.LessThanOrEqual(
                expression.Body,
                Expression.Constant(rangeTo.Value, typeof(DateTime?)
            )
        );

        query.Where(Expression.Lambda<Func<T, bool>>(expressionLT, param));
    }

    return query;

}

用法

var test = session.QueryOver<MyPocoClass>()
            .WhereInOpenEndedDateRange(x=>x.SomeNullableDateField, DateTime.Now, null);
于 2011-05-24T12:56:24.390 回答