2009-07-27 3 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 или структуры сущности, оно не будет работать, поскольку провайдеры не знают, как перевести этот метод. вам нужно сделать некоторые причудливые трюки для этого, чтобы работать –

+0

@Roger все, что вы можете сделать с синтаксисом запроса, также можно сделать вручную, в конечном счете –

+0

вы действительно можете поддерживать вышеуказанные методы в подзапросах, не заменяя всех других методов, таких как select, где или обертывание IQueryable? –

Смежные вопросы