#c# #asp.net #entity-framework #linq #lambda
#c# #asp.net #entity-framework #linq #лямбда
Вопрос:
Я пытаюсь передать список строк, содержащих поля, которые необходимо отфильтровать.
string[] filterList = {"CostCenterId", "Description", ....}
Определение объекта:
public class CostCenter
{
public int Id { get; set; }
public string CostCenterId { get; set; }
public string Description { get; set; }
}
Вместо того, чтобы делать:
var filterData = data
.Where(x => x.CostCenterId.Contains(request.Filter) || x.Description.Contains(request.Filter));
Возможно ли получить атрибут внутри лямбда-выражения: Where()
передав string
вместо этого a?
Возможно ли сделать что-то вроде:
var filterData = data
.Where(x => x["CostCenterId"].Contains(request.Filter) || x.["Desription"]
.Contains(request.Filter));
замена значений из списка фильтров:
var filterData = data
.Where(x => x[filterList[0]].Contains(request.Filter) || x.[filterList[1]
.Contains(request.Filter));
Я попробовал следующий подход:
var filterData = data
.Where(x => x.GetType().GetField("CostCenterId").Name.Contains(filter) || x.GetType().GetField("Description").Name.Contains(filter));
но это не работает,
Ожидаемый результат — отфильтрованные данные. Результат, который я получаю прямо сейчас, равен нулю, любая помощь будет с благодарностью
Комментарии:
1. «это не работает» мало что говорит. Является ли это запросом EF / other ORM? Какую ошибку / неожиданный результат вы получаете?
2. Мои извинения, я забыл упомянуть в своем вопросе, что это запрос EF. Ожидаемый результат — отфильтрованные данные. Результат, который я получаю прямо сейчас, равен нулю.
3. Используйте DynamicLinq , если только вы не делаете это для создания некоторой абстракции поверх EF, например, вы пытаетесь создать
QueryTableWhere("tablename", "columnname1", "value1", "columnname2", "value2")
метод общего типа — в этом случае не беспокойтесь.. В конечном итоге это только сбивает вас с толку, усложняя задачу с каждым поворотом, чем просто написание прямого запроса LINQ в первую очередь
Ответ №1:
EF использует IQueryable
интерфейс, который принимает деревья выражений, чтобы он мог анализировать ваш код и пытаться перевести его в реальный SQL. Один из вариантов здесь — самостоятельно создать выражение фильтра для Where
предложения. Для ограниченного случая обработки только строковых свойств вы можете сделать что-то подобное (крайний случай пустого filterList
опущен):
var filterValue = "test";// request.Filter
string[] filterList = { "CostCenterId", "Description" };
var par = Expression.Parameter(typeof(CostCenter));
var stringContains = typeof(string).GetMethod(nameof(string.Contains), new[] {typeof(string)});
var predicate = filterList
.Select(f =>
{
var prop = Expression.Property(par, typeof(CostCenter), f);
return (Expression) Expression.Call(prop, stringContains, Expression.Constant(filterValue));
})
.Aggregate((agg,curr) => Expression.OrElse(agg,curr));
var filter = Expression.Lambda<Func<CostCenter, bool>>(predicate, par);
А затем использовать его в запросе:
var filterData = data.Where(filter);
Комментарии:
1. Спасибо за это. Я пытался реализовать это решение, но, похоже, получаю следующую ошибку: `’IEnumerable<CostCenter>’ не содержит определения для ‘Where’, а лучший метод расширения перегружает ‘Запрашиваемый. Где<CostCenter>(IQueryable<CostCenter>, выражение<Func<CostCenter, bool>>)’ требуется приемник типа ‘IQueryable<CostCenter>’ ` Это происходит, когда я передаю выражение фильтра в данные. Где()
2. @ezennnn что это за тип
data
?3. Тип
data
IQueryable<CostCenter>4. Оказывается, ошибка заключалась в том, что я изменил IQueryable<CostCenter> на IEnumerable<CostCenter>, изменив его на тип IQueryable, решил проблему. Спасибо
5. @ezennnn Рад, что это помогло. Да, хотел написать, что из-за вашей ошибки ваш тип не
IQueryable
соответствует =).