Динамическое где предложение лямбда в C # - PullRequest
4 голосов
/ 26 августа 2011

У меня есть форма поиска, которая выглядит следующим образом:

search form

Код формы выглядит следующим образом:

@using (Html.BeginForm())
{
    @Html.ValidationSummary()
    <div>
        @Html.DropDownList("SelectedType", Model.TypeOptions)
        @Html.DropDownList("SelectedSearch", Model.SearchOptions)
        @Html.TextBoxFor(x => x.SearchTerm)
        <input type="submit" value="Search" />
    </div>
}

Что я хочуdo - это динамическое построение лямбда-выражения where из опций возврата.Например, если пользователь выбирает «Process No» и «Contains», то лямбда будет выглядеть как

model.DataSource = _db.InstrumentLists.Where(x => x.Process_No.Contains(SearchTerm));

Или если пользователь выбирает «PLC No» и «Equals», тогда лямбда будет выглядеть как

model.DataSource = _db.InstrumentLists.Where(x => x.PLC_No == SearchTerm);

Я пытаюсь сделать это, избегая большого оператора case или стека if, т.е. я не хочу следующее:

if (SelectedType == "Process No" And SelectedSearch = "Contains")
   model.DataSource = _db.InstrumentLists.Where(x => x.Process_No.Contains(SearchTerm));
elseif (SelectedType == "Process No" And SelectedSearch = "Equals")
   model.DataSource = _db.InstrumentLists.Where(x => x.Process_No == SearchTerm);
...

По сути, я хочу передатьссылка на свойство класса, что-то, чтобы указать тип теста (то есть содержит, равно, начинается с и т. д.) и поисковый термин для функции, или что-то в том же духе, и получить предикат для вставки в мое предложение Where.Я хочу, чтобы эта функция работала динамически, поэтому мне не нужно изменять ее для каждой комбинации свойства и типа теста.

Возможно ли это или является единственным способом использования Where с параметром предиката строки?

Редактировать : Если это важно, я использую EF для своей модели данных, поэтому _db.InstrumentLists возвращает ObjectSet<InstrumentList>.

Ответы [ 3 ]

2 голосов
/ 26 августа 2011

у вас есть 2 варианта здесь:

  • создает метод поиска на основе «переключения», т. Е. В зависимости от значения выбора пользователя выполняет другое Where и возвращает источник данных

  • используйте Dynamic Linq и создайте Where из строки

РЕДАКТИРОВАТЬ - пример для Dynamic Linq:

model.DataSource = _db.InstrumentLists.Where(SelectedType + " == @0", SearchTerm);
1 голос
/ 26 августа 2011

От макушки головы (сейчас я не могу попробовать ...):

public bool GetComparativeFunction(String property, SearchModel options)
{
    if (options.SelectedSearch == "Contains") return property.Contains(options.SearchTerm);

    if (options.SelectedSearch == "Equals") return property.Equals(options.SearchTerm);

    return false; //default option
}

public Expression<Func<InstrumentLists, bool>> GetLambdaExpressionFromFilter(SearchModel options)
{
    if (options.SelectedType == "Process_No")
        return p => GetComparativeFunction(p.Process_No, options);

    if (options.SelectedType == "PLC_No")
        return p => GetComparativeFunction(p.PLC_No, options);

    return p => true; //default option
}

Тогда в вашем запросе:

model.DataSource = _db.InstrumentLists.Where(GetLambdaExpressionFromFilter(Model));

Я не уверен, что он работает с IQueryable <>, но вы всегда можете удалить часть Expression <>, если можете работать с IEnumerable <>

1 голос
/ 26 августа 2011

Используйте предикат butilder для динамического создания предложения where.

Проверьте эту статью на предмет наличия: Динамический запрос с Linq .

Пример:

        var predicate = PredicateBuilder.True();

        if(!string.IsNullOrEmpty(txtAddress.Text))
            predicate = predicate.And(e1 => e1.Address.Contains(txtAddress.Text));
        if (!string.IsNullOrEmpty(txtEmpId.Text))
            predicate = predicate.And(e1 => e1.Id == Convert.ToInt32(txtEmpId.Text));


        EmployeeDataContext edb= new EmployeeDataContext();
        var emp = edb.Employees.Where(predicate);
        grdEmployee.DataSource = emp.ToList();
        grdEmployee.DataBind();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...