AnswerIsNot42
AnswerIsNot42

Reputation: 25

C# Lambda - Where - Mulitple expressions of the same criteria

Hypothetical - A party store wants to select people based on criteria from their DB.

DB name "BirthDays" fields: Day, Month, Year

The "where" needs to be dynamic to take in each consideration for search instance:

  1. Day = 12, Month = 1, Year = 1962
  2. Day = 3, Month = 4, Year = 1977 ; Day = 13, Month = 4, Year = 1977
  3. Day = 20, Month = 8, Year = 1941 ; Day = 9, Month = 1, Year = 1991 ; Day = 19, Month = 11, Year = 1986 ; Day = 25, Month = 2, Year = 1956

Below obviously will not work because it only considers one search instance when there may be 3 or even 10:

query.Where(o => o.Day == 3 && o.Month == 4 && o.Year == 1997);

I tried looking into Expression and ParameterExpression, but couldn't wrap my head around it.

[NOTE] @Luaan is the closest one so far, adding "||" will not address #1.

Upvotes: 0

Views: 103

Answers (3)

Luaan
Luaan

Reputation: 63722

If you need to build this dynamically, it's pretty easy with a couple of extension methods. For example:

public static Expression<Func<T, bool>> False<T>(this IQueryable<T> @this)
  => _ => false;

public static Expression<Func<T, bool>> Or<T>
  (this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
  =>
  Expression.Lambda<Func<T, bool>>
  (
    Expression.OrElse
    (
      left, 
      Expression.Invoke
      (
        right, 
        left.Parameters.Cast<Expression>()
      )
    ), 
    left.Parameters
  );
}

Then you can do something like this:

var predicate = query.False();

foreach (var date in filterDates)
{
  predicate = 
    predicate.Or(i => i.Day == date.Day && i.Month == date.Month && i.Year == date.Year);
}

query = query.Where(predicate);

Upvotes: 0

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

Why not load the dates into, say HashSet<DateTime>?

   HashSet<DateTime> birthDays = new HashSet<DateTime>() {
     new DateTime(1962, 1, 12), 
     new DateTime(1977, 4, 3), 
     ...
   };

   ...

   var result = query
    .Where(o => birtDays.Contains(o));

Or I've missed something?

Upvotes: 3

user1017882
user1017882

Reputation:

I'm going to post this and take on the risk of being downvoted. But, in case I haven't missed the point, you can use an || (or) condition in your where:

query.Where(o => (o.Day == 12 && o.Month ==14 && o.Year == 1962) ||
                 (o.Day == 3 && o.Month == 4 && o.Year == 1977));

NOTE: This doesn't cater for all of the scenarios you've listed. Simply append more conditions on and be careful to use parenthesis to separate them correctly.

Upvotes: 5

Related Questions