Burcay Burcay - 3 years ago 73
C# Question

Expression Func with List<T>.Select().Contains()

Here is my generic repository class method:

public IEnumerable<T> GetBy(Expression<Func<T, bool>> condition)
return Context.Set<T>().Where(condition).ToList();

And I want to call it like:

resultCandidate = _repo.GetBy(p => members.Select(s=>s.MemberID).Contains(p.CandidateMemberID)).ToList();

But when I try it it threw an error like that "Unable to create a constant value of type
. Only primitive types or enumeration types are supported in this context."

I should call the method like that. And I tried to
and it worked but not worked like what i want. Because it doesn't get the where clauses when generating SQL query.

Note: members is a


Answer Source

Your method is ok. But you need to move the member ID list outside of the expression (that's what the exception message is trying to indicate), thus satisfying the primitive type list requirement:

var memberIds = members.Select(s=>s.MemberID).ToList();
resultCandidate = _repo.GetBy(p => memberIds.Contains(p.CandidateMemberID)).ToList();

UPDATE: Well, if it's so critical for you to call it exactly that way, then you can try the following quite naïve ExpressionVisitor:

using System.Linq.Expressions;

class ExpandSelectVisitor : ExpressionVisitor
    protected override Expression VisitMethodCall(MethodCallExpression node)
        if (node.Method.DeclaringType == typeof(Enumerable) && node.Method.Name == "Select")
            return Expression.Constant(Expression.Lambda(node).Compile().DynamicInvoke());
        return base.VisitMethodCall(node);

and use it inside your generic repository method like this:

public IEnumerable<T> GetBy(Expression<Func<T, bool>> condition)
    condition = condition.Update(
        new ExpandSelectVisitor().Visit(condition.Body), condition.Parameters);

    return Context.Set<T>().Where(condition).ToList();
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download