C语言中的动态Where子句lambdas

时间:2011-08-26 05:10:48

标签: c# .net lambda

我的搜索表单如下:

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>
}

我想要做的是从return选项中动态构造lambda where子句。例如。如果用户选择“Process No”和“Contains”,则lambda看起来像

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

或者,如果用户选择“PLC No”和“Equals”,则lambda看起来像

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

我正在尝试这样做,同时避免大案例陈述或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 个答案:

答案 0 :(得分:2)

这里有2个选项:

  • 制作一个基于“开关”的搜索方法,即根据用户选择的值执行不同的Where并返回一个DataSource

  • 使用Dynamic Linq并从字符串构建Where

编辑 - 动态Linq的例子:

model.DataSource = _db.InstrumentLists.Where(SelectedType + " == @0", SearchTerm);

答案 1 :(得分:1)

利用谓词butilder动态构造where子句。

查看本文以了解deatil:Dynamic query with 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();

答案 2 :(得分:1)

从我的头顶(我现在不能尝试......):

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&lt;&gt;但你总是可以删除Expression&lt;&gt;部分如果您可以使用IEnumerable&lt;&gt;