2009-07-27 48 views
1

我對linq相當陌生,並希望通過擴展IQueryable深入研究一下。我想創建一個查詢日期範圍的簡單擴展方法。東西將相當於:擴展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 
} 

這是可能的,如果是的話,我該怎麼做?

回答

4

未經檢驗的,但是:

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); 
} 

有關信息,雖然,我通常認爲範圍是>= start< 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否則會導致大問題)

+0

另一個注意事項:這隻會在最外層的IQueryable上工作,如果你在linq到sql或實體框架的子查詢中使用它,它將會失敗,因爲提供者不知道如何翻譯這個方法。你必須做一些更好的技巧才能工作 – 2013-03-23 14:54:49