Tomasz Madeyski
Tomasz Madeyski

Reputation: 10890

WhereIn with dynamic property

I want to build LINQ which will be later translated to the WHERE IN in sql. In regular use case I would do:

(querable is IQuerable<T> and arr is IEnumerable<int>)

querable = querable.Where(e => arr.Contains(e.Id));

BUT

my issue is that the value I want to filter (e.Id) is dynamic, and I get it as a string. How can I do that?

Some more background: I'm doing REST API endpoint in which user can send by which column he wants to filter values, so examples would be:

  1. filter: {"id": [1,2]}

Which I want to translate into something like queryable.Where(e => new [] {1,2}.Contains(e.Id))

  1. filter: {"customerId": [4,5]}

Which I want to translate into something like queryable.Where(e => new [] {4,5}.Contains(e.CustomerId))

So basically my input is a column name which is a string and list of ids which is IEnumerable<int>

I feel it can be achieved by using Expression (similar to this answer) but I don't know how to do it.

Upvotes: 4

Views: 206

Answers (1)

Evk
Evk

Reputation: 101483

You can do it like this:

public static class QueryableExtensions {
    public static IQueryable<TEntity> WhereIn<TEntity, TValue>(this IQueryable<TEntity> query, string property, IEnumerable<TValue> values) {
        // x
        var arg = Expression.Parameter(typeof(TEntity), "x");
        // x.Property            
        var prop = Expression.Property(arg, property);
        // values.Contains(x.Property)
        var contains = Expression.Call(
            typeof(Enumerable),
            "Contains",
            new[] { typeof(TValue) },
            Expression.Constant(values),
            prop
        );
        // x => values.Contains(x.Property)
        var lambda = Expression.Lambda<Func<TEntity, bool>>(contains, arg);
        return query.Where(lambda);
    }
}

Note that type of values in enumerable you pass, and property type should match for this to work (so if property is of type int - pass array of ints).

Upvotes: 2

Related Questions