1

Let's say I have these two entities :

  • Document, which contains a DateTime property (called Date).
  • Period, which contains two DateTime properties (called DateFrom and DateTo) that represents a period of time.

Then, consider this expression, in which d represents a Document and p represents a Period, that is used to filter a Document collection to return only those who are part of a given Period :

d => d.Date >= p.DateFrom && d.Date <= p.DateTo

The problem is, given a collection of Period entities, how could I build a lambda expression which represents a concatenation of multiple expressions like the above expression, so it gives :

d => 
     (d.Date >= p1.DateFrom && d.Date <= p1.DateTo) 
  && (d.Date >= p2.DateFrom && d.Date <= p2.DateTo) 
  && (d.Date >= p3.DateFrom && d.Date <= p3.DateTo) 
  && ...

I want the result to be a lambda expression that I can further combine to other conditions before filtering my Document collection.

  • Would it not be easier to restrict the result set in stages, rather than all in one big && fest? If you're using Linq, it will build them up anyway, until you request data back. – Mikey Mouse May 10 '13 at 14:16

2 Answers2

4
var documentsInAllPeriods = documents.Where(d => periods.All(p => 
    d.Date >= p.DateFrom && d.Date <= p.DateTo));

(Note you can change All to Any if you want the documents in any period rather than the documents in every period.)

Servy
  • 202,030
  • 26
  • 332
  • 449
  • I have edited my question to be more precise about what I want to acheive. I want to be able to combine that Expression to another Predicate. –  May 10 '13 at 14:18
  • @JoanLeaven It seems you're not particularly familiar with the terminology that you're using, because this answer meets the exact criteria of your question. FYI I would think that this would work for either an `IQueryable` or an `IEnumerable`. Have you tried it and seen it not work for an `IQueryable`? – Servy May 10 '13 at 14:20
  • It's because I haven't found a way to make this work : http://stackoverflow.com/questions/16469268/building-a-custom-predicate-to-act-as-a-filter-using-a-foreach-loop –  May 10 '13 at 14:21
  • @JoanLeaven So you tried this code and it didn't run properly? If you just want someone to fix your other code then asking the same question again isn't appropriate, see [How do I get attention for old, unanswered questions?](http://meta.stackexchange.com/questions/7046/how-do-i-get-attention-for-old-unanswered-questions) – Servy May 10 '13 at 14:23
  • I really want to be able to build a lambda expression out of this. I want to be able to use the resulting lambda expression as a filter against other filters before calling Where on an ObjectSet. –  May 10 '13 at 14:26
  • @JoanLeaven Then pull the lambda out; I fail to see the problem with that. `Expression> e = d=> ExpressionFromAnswer;` What's the problem? Note that if you simply want to apply additional filters there's no need to pull out the expression; just call `Where` multiple times with each filter you want to apply. It's much easier. – Servy May 10 '13 at 14:28
  • I am not filtering in-memory collection. It has to be sent to linq-to-entities to build a SQL query. –  May 10 '13 at 14:32
  • 1
    @JoanLeaven I'm aware of that. It in no way changes my comment. You can apply multiple `Where` calls to a single query, even a dynamic number of `Where` calls. I do it all the time. It's much easier than trying to hack together a single predicate, when it can be done. – Servy May 10 '13 at 14:34
  • Well, this will make me go into a totally new direction. I will try to apply multiple Where calls to avoid dynamically building a single predicate. Thanks. –  May 10 '13 at 14:42
0

Assuming the collection of period entities (periods) is available for the lambda expression:

(d) => 
{ 
   bool cond = false;
   foreach(Period p in periods)  
   {
      // check period
      // return earlier if condition not met
   }

   return cond;
}
dinony
  • 614
  • 3
  • 13