Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending IQueryable with IsInDateTimeRange

So I am getting somewhat tired of rewriting the same queries over and over again.

repo.Query().Where(stuff => stuff.Timestamp >= minTime && stuff.Timestamp <= maxTime && ...);

I thought I should extend IQueryable with a method called IsInDateTimeRange, and use it like this

repo.Query().IsInDateTimeRange(stuff => stuff.Timestamp, minTime, maxTime) ...

this would be very easy for IEnumerable, just a Func<T, DateTime> and two DateTimes, however for the IQueryable I needs to take an Expression and I am not really sure how to use this.

This was my attempt, but does not seem to be working.

public static IQueryable<TValue> IsInDateTimeRange<TValue>(
        this IQueryable<TValue> self,
        Expression<Func<TValue, DateTime>> getMember,
        DateTime minTime,
        DateTime maxTime)
    {
        return self.Where(value => minTime >= getMember(value) && maxTime <= getMember(value));
    }
like image 509
jool Avatar asked Jan 30 '23 15:01

jool


1 Answers

You can accomplish this by manually building the expression based on the property access expression that is passed to the method:

public static IQueryable<TValue> IsInDateTimeRange<TValue>(
    this IQueryable<TValue> self,
    Expression<Func<TValue, DateTime>> getMember,
    DateTime minTime,
    DateTime maxTime)
{
    var getMemberBody = getMember.Body;
    var filter = Expression.Lambda<Func<TValue, bool>>(
        Expression.And(
            Expression.LessThanOrEqual(
                Expression.Constant(minTime),
                getMemberBody
            ),
            Expression.LessThanOrEqual(
                getMemberBody,
                Expression.Constant(maxTime)
            )
        ),
        getMember.Parameters
    );
    return self.Where(filter);
}
like image 116
Titian Cernicova-Dragomir Avatar answered Feb 02 '23 11:02

Titian Cernicova-Dragomir