Reputation: 315
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
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 fromAttr3
you should pass 3 asstart
argument.
Upvotes: 2