I have written this filter to get only documents that match certain periods of time from the database :
The Period entity is straightforward and contains two properties : DateFrom and DateTo.
I need to build a filter from lambdas, each one for each Period that is submitted to build the filter.
The filter, when is completely built, has to look like this :
ObjectSet.Where(d =>
(d.Date >= Period1.DateFrom && d.Date <= Period1.DateTo)
|| (d.Date >= Period2.DateFrom && d.Date <= Period2.DateTo)
|| (d.Date >= Period3.DateFrom && d.Date <= Period3.DateTo));
As you can guess, I have to dynamically build this filter because the number of submitted periods to build the filter can vary.
(The following is the Expression
I use to combine the lambdas (each one for each period of time that have been submitted to build the filter)
private Expression<Func<T, bool>> CombineWithOr<T>(
Expression<Func<T, bool>> firstExpression,
Expression<Func<T, bool>> secondExpression)
{
var parameter = Expression.Parameter(typeof(T), "x");
var resultBody = Expression.Or(
Expression.Invoke(firstExpression, parameter),
Expression.Invoke(secondExpression, parameter));
return Expression.Lambda<Func<T, bool>>(resultBody, parameter);
}
Here is where I combine each lambda for each period there is to add to the document filter :
public IList<Document> GetDocuments(IList<Periods> periods)
{
Expression<Func<Document, bool>> resultExpression = n => false;
foreach (var submittedPeriod in periods)
{
var period = submittedPeriod;
Expression<Func<Document, bool>> expression =
d => (d.Date >= period.DateFrom && d.Date <= period.DateTo);
resultExpression = this.CombineWithOr(resultExpression, expression);
}
var query = this.ObjectSet.Where(resultExpression.Compile());
}
The problem is, when I launch deferred execution of the query ...
var documents = query.ToList();
... and I look at the resulting SQL, nothing is added to the SELECT statement.
If I execute the query without compiling the resulting Expression like this :
var query = this.ObjectSet.Where(resultExpression);
I get this exception :
The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
That means that the Linq-To-Entities query provider doesn't know how to translate my filter into SQL code.
What is bugging me right now is how such a simple DateTime comparison from entities (Document and Period) that are both part of my Entity schema can mess up the provider ?
Any ideas how I can achieve such a filtering ?