anesthetic
anesthetic

Reputation: 315

Where comparison from array

I have an sql table with the following structure:

Id-------|-------Attr1-------|-------Attr2------|------Attr3------|

1--------|--------true-------|------false-------|------false------|

2--------|--------true-------|------true--------|-------true-------|

And so on with different combinations of true/false.

I am trying to construct a Linq query that can pull the correct Id given a known combination of true/false.

For example, I could use the following:

public int GetTypeId(string[] arr)
    {
        //arr[0] is true, arr[1] is false
        return _context.Types
            .FirstOrDefault(x => x.Attr1 == arr[0] && x.Attr2 ==arr[1]).Id;
    }

And that would yield an Id of 1.

Now my question is how to properly make this a dynamic function where there are 10 attributes columns, and I can input an array with an arbitrary number of elements to make the where comparison (say Attr1 and Attr2 the first time, then Attr3 and Attr4 and Attr5 the next).

Is there an efficient way to do this? My biggest issue is that the .FirstOrDefault() function does not accept a concatenated string.

Upvotes: 0

Views: 101

Answers (1)

Slava Utesinov
Slava Utesinov

Reputation: 13488

You should dynamically create Expression predicate:

public int GetTypeId(string[] arr, int start = 1)
{
    var arg = Expression.Parameter(typeof(TypeClass), "x");            
    Expression andExpr = null;
    for(var i = 0; i < arr.Length; i++)
    {
        var exprProp = Expression.Property(arg, "Attr" + (i + start));
        var exprVal = Expression.Constant(arr[i]);
        var exprEq = Expression.Equal(exprProp, exprVal);
        andExpr = andExpr == null ? exprEq : Expression.AndAlso(andExpr, exprEq);
    }                        
    var predicate = Expression.Lambda<Func<TypeClass, bool>>(andExpr, arg);

    return _context.Types.FirstOrDefault(predicate).Id;
}

If you want to start comparison not from Attr1(default behavior), but from Attr3 you should pass 3 as start argument.

Upvotes: 2

Related Questions