【问题标题】:Extending IQueryable and parsing a property扩展 IQueryable 并解析属性
【发布时间】:2010-11-14 07:01:02
【问题描述】:

我对 linq 还很陌生,想通过扩展 IQueryable 来更深入地研究。我想创建一个查询日期范围的简单扩展方法。相当于:

IQuerable.Where(x => x.Date > fromDate && x.Date < toDate);

但在日期上有一些额外的处理。我希望能够解析一个属性来执行查询,所以方法调用将类似于:

IQueryable.WhereDateRange(x => x.Date, fromDate, toDate);
IQueryable.WhereDateRange(x => x.AnotherDate, fromDate, toDate);

我一直在研究类似下面的内容,但我不完全确定自己在做什么

public static IQueryable<T> WhereDateRange<T>(this IQueryable<T> source, Func<T, DateTime> getter, DateTime from, DateTime to) {
//query here
}

这可能吗?如果可以,我该怎么做?

【问题讨论】:

    标签: c# c#-3.0


    【解决方案1】:

    未经测试,但是:

    public static IQueryable<T> WhereDateRange<T>(
        this IQueryable<T> source, Expression<Func<T, DateTime>> getter,
        DateTime from, DateTime to)
    {
        Expression body = getter.Body;
    
        var predicate = Expression.Lambda<Func<T, bool>>(
            Expression.And(
                Expression.GreaterThan(body, Expression.Constant(from)),
                Expression.LessThan(body, Expression.Constant(to))
            ),
            getter.Parameters);
        return source.Where(predicate);
    }
    

    不过,仅供参考;我通常假设一个范围是&gt;= start 和&lt; end,所以我会使用Expression.GreaterThanOrEqual。

    使其更可重用(并注意我在这里使用GreaterThanOrEqual):

    public static IQueryable<T> WhereInRange<T, TValue>(
        this IQueryable<T> source, Expression<Func<T, TValue>> selector,
        TValue from, TValue to)
    {
        Expression body = selector.Body;
    
        var predicate = Expression.Lambda<Func<T, bool>>(
            Expression.And(
                Expression.GreaterThanOrEqual(
                    body, Expression.Constant(from, typeof(TValue))),
                Expression.LessThan(
                    body, Expression.Constant(to, typeof(TValue)))
            ),
            selector.Parameters);
        return source.Where(predicate);
    }
    

    (这种情况需要在常量上指定TValue,否则null会出大问题)

    【讨论】:

    • 另一个注意事项:这仅适用于最外层的 IQueryable,如果您在 linq to sql 或实体框架的子查询中使用它,它将失败,因为提供者不知道如何翻译此方法.你必须做一些更花哨的技巧才能让它工作
    • @Roger 你可以用查询语法做的任何事情最终也可以手动完成
    • 你真的可以在子查询中支持上述方法,而不用替换所有其他方法,如 select、where 或包装 IQueryable 吗?
    • 您将不得不手动编写整个内容,这并不漂亮,但可以肯定:您可以做到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多