3

I am using LINQ to Entities and querying for entries within a certain date time period, held in model object which has the properties DateFrom and DateTo. To do this I can use the following to create a sequence

var allActiveLogs = this.repository.RoutePerformanceLogs
         .Where(log => log.Date >= model.DateFrom.Value && 
                log.Date <= model.DateTo.Value)

If I want to abstract this out for reuse I can create the following expression (as long model is in scope).

Expression<Func<RoutePerformanceLog, bool>> logWithinDateBounds = log => 
        log.Date >= model.DateFrom.Value && log.Date <= model.DateTo.Value;

and then later call

var allActiveLogs = this.repository.RoutePerformanceLogs.Where(logWithinDateBounds)

What I would like to do is abstract this expression further, to code where model is not in scope, possibly using an expression of signature

Expression<Func<RoutePerformanceLog, DateTime?, DateTime?, bool>> logWithinDateBounds

However, this won't work within a Where method, as the where method requires a Func<T, boolean> or an Expression<Func<T, boolean>>.

Is it possible to have a reusable expression, that takes more than one parameter and can be used to filter an IQueryable collection (preferably using the query provider to do the filtering rather than filtering objects in memory).

João Angelo
  • 56,552
  • 12
  • 145
  • 147
AlexC
  • 10,676
  • 4
  • 37
  • 55

1 Answers1

2

I hope this can help. It is a quite functional programming approach. You can create a function (or an Expression) returning a function and using that function for the Where.

Something like the following:

Func<int, int, Func<int,bool>> func = (x, y) => z=> x + y > z;
var list = new List<int> { 1, 2, 3, 4, 5, 6 };

Console.WriteLine("How many greater than 2+1? {0}", 
                  list.Where(func(1, 2)).Count());
Console.WriteLine("How many greater than 3+1? {0}", 
                  list.Where(func(3, 1)).Count());
Console.WriteLine("How many greater than 2+3? {0}", 
                  list.Where(func(2, 3)).Count());
Console.ReadKey();

In your case you need:

Func<DateTime, DateTime, Expression<Func<RoutePerformanceLog, bool>>> logWithinDateBounds =         
    (dateFrom, dateTo) => 
       log => log.Date >= dateFrom && log.Date <= dateTo;
AlexC
  • 10,676
  • 4
  • 37
  • 55
Teudimundo
  • 2,610
  • 20
  • 28