-3

I have a situation where I am using a linq provider that does not support the .Contains method to generate a WHERE IN clause in the query. I am looking for a way to generate the (Value = X OR Value = Y OR Value = Z) statement dynamically from the list of items to match. I haven't found a good example of building expression trees to do this.

Normally I would query this way:

var names = new string[] { "name1", "name2", "name3" }
var matches = query.Where(x => names.Contains(x.Name));

So far the closest thing I could find was to use the Dynamic Linq Library and build a string to be interpreted but it feels a bit too hacky.

Jason Rodman
  • 71
  • 1
  • 5

2 Answers2

0

You don't even need an external library for something like this:

var names = new string[] { "name1", "name2", "name3" };

// Where MyClass is the type of your class
ParameterExpression par = Expression.Parameter(typeof(MyClass));
MemberExpression prop = Expression.Property(par, "Name");

Expression expression = null;

foreach (string name in names)
{
    Expression expression2 = Expression.Equal(prop, Expression.Constant(name));

    if (expression == null)
    {
        expression = expression2;
    }
    else
    {
        expression = Expression.OrElse(expression, expression2);
    }
}

var query = ...; // Your query

if (expression != null)
{
    // Where MyClass is the type of your class
    var lambda = Expression.Lambda<Func<MyClass, bool>>(expression, par);
    query = query.Where(lambda);
}

You can build a concatenation of Expression.OrElse, with the comparisons between the property Name and one of the strings.

In this particular case (3 strings), the resulting Expression, when looked from the debugger, is:

(((Param_0.Name == "name1") OrElse (Param_0.Name == "name2")) OrElse (Param_0.Name == "name3"))
xanatos
  • 109,618
  • 12
  • 197
  • 280
0

Just improving the answer by xanatos:

var names = new string[] { "name1", "name2", "name3" };

var query = ...; // Your query

if (names.Any())
{
    // Where MyClass is the type of your class
    ParameterExpression par = Expression.Parameter(typeof(MyClass));
    MemberExpression prop = Expression.Property(par, "Name");

    var expression=names
        .Select(v => Expression.Equal(prop, Expression.Constant(v)))
        .Aggregate(Expression.OrElse);

    // Where MyClass is the type of your class
    var lambda = Expression.Lambda<Func<MyClass, bool>>(expression, par);
    query = query.Where(lambda);
}
Robert McKee
  • 21,305
  • 1
  • 43
  • 57