Я пытаюсь создать динамический AndAlso
фильтр, который будет использоваться в методе Where
к LINQ-to-EF
запросу:Параметр Замена, когда параметр является сложным объектом
query.Where(filterExpression)
где filterExpression
представляет собой скомпилированная лямбда
До сих пор я реализовал цикл с некоторым причудливым использованием, чтобы проверять случаи, когда есть только один, два или более запросов.
Expression selectLeft = null;
Expression selectRight = null;
Expression filterExpression = null;
foreach (QueryColumn columnQuery in querycolumns)
{
Expression<Func<FileColumnRecords, bool>>
columnPredicate = d => d.fcv.Any(f => (f.value != null ?
f.value.ToLower().Contains(columnQuery.queryTerm.ToLower()) :
false));
if (selectLeft == null)
{
selectLeft = columnPredicate.Body;
filterExpression = selectLeft;
continue;
}
if (selectRight == null)
{
selectRight = columnPredicate.Body;
filterExpression =
Expression.AndAlso(selectLeft, selectRight);
continue;
}
filterExpression =
Expression.AndAlso(filterExpression, columnPredicate.Body);
}
Затем я создал ParameterReplacer
, чтобы гарантировать, что все итерации моего параметра выражения получить ту же ссылку:
ParameterExpression param = Expression.Parameter(typeof(FileColumnRecords), "p");
ParameterReplacer replacer = new ParameterReplacer(param);
filterExpression = replacer.Visit(filterExpression);
, который построен из:
class ParameterReplacer : ExpressionVisitor
{
private readonly ParameterExpression parameter;
internal ParameterReplacer(ParameterExpression parameter)
{
this.parameter = parameter;
}
protected override Expression VisitParameter
(ParameterExpression node)
{
return parameter;
}
}
(ParameterReplacer
класс любезно JonSkeet)
При запуске t он ParameterReplacer
я получаю следующее сообщение об ошибке:
"Property 'System.String value' is not defined for type 'Models.FileColumnRecords'"
где FileColumnRecords
определяется как:
public class FileColumnRecords
{
public Documents doc;
public IEnumerable<FileColumnValues> fcv;
}
и FileColumnValues
как:
public partial class FileColumnValues
{
public long ID { get; set; }
public long CNID { get; set; }
public long fileID { get; set; }
public string value { get; set; }
}
Спасибо, что ответили, Джон! 'PredicateBuilder' выглядит действительно интересным. Вы думаете, что можно передать весь мой «columnPredicate» в «PredicateBuilder» или мне нужно будет построить дерево выражений, как вы предлагаете в своем ответе? – seebiscuit
@ Пояснение: Я не совсем понимаю, что вы делаете, но я подозреваю, что вы можете передать весь «columnPredicate». –
Это определенно стоит попробовать. Позвольте мне взять это на тест-драйв. – seebiscuit