2011-08-26 74 views
3

我有一個看起來像這樣的搜索形式:動態Where子句lambda表達式在C#

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

我想要做的就是從返回選項動態構造一個lambda where子句。例如。如果用戶選擇「過程中沒有」和「包含」,那麼拉姆達會是什麼樣

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

或者,如果用戶選擇「PLC否」和「等於」,那麼拉姆達會是什麼樣

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

我試圖做到這一點,同時避免大的case語句或如果堆棧,即我不希望做如下:

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>

回答

1

你有2個選擇這裏:

  • 使根據用戶選擇的價值基礎的「開關」的搜索方法,即執行不同的地方,並返回一個DataSource

  • 使用Dynamic Linq並從字符串構造Where

編輯 - 例如動態的LINQ:

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

用我的目標更新了我的問題,請參閱粗體部分。 – link664

+0

你可以用動態Linq來完成大部分工作 - 它需要一個你構造的字符串......就像我的例子 - 搜索的屬性/字段直接從字符串SelectedType和SearchTerm中獲取,Weher被調用字符串並對SelectedType/SearchTerm的任意組合執行此操作...查看我答案中的鏈接... – Yahia

1

利用謂詞butilder動態地構造where子句。

查看本文後面的數據: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(); 
+0

@ link664 - 請檢查文章,其中包含謂詞構建器網站的鏈接,您可以在其中找到需要包含在項目中的一個文件 –

+0

@ link664 http://www.albahari.com/nutshell/ predicatebuilder.aspx他是否有源代碼和鏈接到圖書館 – xanatos

+0

我很難看出這比如果我直接在每個if語句中直接調用Where語句更好(請參閱我編輯的問題)。它仍然意味着我需要一個額外的if語句每個SelectedType和SelectedSearch組合。 – link664

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 <>但你總是可以去除表達<>部分,如果你可以用一個IEnumerable工作<>