Этот вопрос действительно интересовал меня, и я попытался скомпилировать что-то работающее без использования сторонних библиотек.Далее я представлю фрагменты кода, которые вместе дали желаемый результат.Но, скорее всего, это все в образовательных целях.
Во-первых, нам нужны функция и класс, взятые отсюда: https://www.c -sharpcorner.com / UploadFile / c42694 / dynamic-query-in-linq-используя-предикат-строитель /
static Expression<T> Compose<T>(Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
{
// zip parameters (map from parameters of second to parameters of first)
var map = first.Parameters
.Select((f, i) => new { f, s = second.Parameters[i] })
.ToDictionary(p => p.s, p => p.f);
// replace parameters in the second lambda expression with the parameters in the first
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
// create a merged lambda expression with parameters from the first expression
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
class ParameterRebinder : ExpressionVisitor {
readonly Dictionary<ParameterExpression, ParameterExpression> map;
ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
protected override Expression VisitParameter(ParameterExpression p)
{
ParameterExpression replacement;
if (map.TryGetValue(p, out replacement))
{
p = replacement;
}
return base.VisitParameter(p);
}
}
Тогда мы можем сделать что-то вроде этого (я использовал кортежи, потому что они больше соответствуют идее):
var tup = new List<Tuple<string, string>> {
new Tuple<string, string>("CO", "YL"),
new Tuple<string, string>("VA", "CD")
};
Expression<Func<YOUR_TYPE_HERE, bool>> baseFunc = t => false;
foreach (var a in tup)
{
Expression<Func<YOUR_TYPE_HERE, bool>> addFunc = t => t.store == a.Item1 && t.brand == a.Item2;
baseFunc = Compose(baseFunc, addFunc, Expression.OrElse);
}
var res = _context.YOUR_ENTITY_NAME.Where(baseFunc).ToList();
Iпроверил, что он выполняется в одном запросе и оценил на стороне базы данных.
UPD: Если вы хотите повысить производительность и хотите использовать бит sql:
var res = context.YOUR_ENTITY_NAME.FromSql("SELECT * FROM YOUR_ENTITY_NAME WHERE (...and...) or (...and...)").ToList();
Вы можете сгенерировать часть "где" вручную и поместить ее как строку в конце на "SELECT * FROM YOUR_ENTITY_NAME WHERE"
.Но будьте осторожны с уколами.Здесь вам нужно использовать параметры.