2011-04-15 45 views
10

我有一個場景,我必須在LINQ中使用動態條件。LINQ中動態的條件

我想是這樣的:

public void test(bool flag) 
{ 
    from e in employee 
    where e.Field<string>("EmployeeName") == "Jhom" 
    If (flag == true) 
    { 
     e.Field<string>("EmployeeDepartment") == "IT" 
    } 
    select e.Field<string>("EmployeeID") 
} 

我知道我們不能用「如果」在LINQ查詢的中間,但究竟是什麼解決辦法嗎?

請幫助...

+0

它不是真的*動態*,你需要做的就是明確調用LINQ方法並根據條件鏈接它們。 – 2011-04-15 09:55:40

回答

9

所以,如果flagfalse你需要的所有Jhoms,如果flag是真實的,你只需要在Jhoms IT部門

這種情況

!flag || (e.Field<string>("EmployeeDepartment") == "IT" 

滿足該標準(如果標誌爲假,等等),所以查詢將變爲:

from e in employee  
where e.Field<string>("EmployeeName") == "Jhom" 
    && (!flag || (e.Field<string>("EmployeeDepartment") == "IT") 
select e.Field<string>("EmployeeID") 

也,這e.Field<string>("EmployeeID")業務,聞起來像softcoding,可能需要考慮這樣做。我猜

from e in employee  
where e.EmployeeName == "Jhom" 
    && (!flag || (e.EmployeeDepartment == "IT") 
select e.EmployeeID 

會更緊湊,不太容易出現打字錯誤。


編輯:此答案適用於此特定場景。如果你有很多這樣的查詢,通過一切手段投資其他答案中提出的模式。

+0

這是最直接的。 – 2016-10-07 14:26:57

10

請查看完整的博客文章:Dynamic query with Linq

有兩個選項可以使用:

Dynamic LINQ library

string condition = string.Empty; 
if (!string.IsNullOrEmpty(txtName.Text)) 
    condition = string.Format("Name.StartsWith(\"{0}\")", txtName.Text); 

EmployeeDataContext edb = new EmployeeDataContext(); 
if(condition != string.empty) 
{ 
    var emp = edb.Employees.Where(condition); 
///do the task you wnat 
} 
else 
{ 
//do the task you want 
} 

Predicate Builder

Predica TE生成器的工作原理類似於動態LINQ庫,但它是類型安全的:以上庫之間

var predicate = PredicateBuilder.True<Employee>(); 

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

EmployeeDataContext edb= new EmployeeDataContext(); 
var emp = edb.Employees.Where(predicate); 

區別:

  • PredicateBuilder允許建立類型安全的動態查詢
  • 動態LINQ庫允許使用動態構建查詢Where和OrderBy子句使用字符串指定。
+0

第一個例子似乎脫離了上下文。如果它剛分配了'string.Empty',那麼檢查'condition'是否爲空?我現在要糾正這個問題.. – 2011-04-15 09:43:39

+0

@gaearon - 如果有更多的條件多數民衆贊成把放在那裏...我alreay張貼完整的職位,你可以看到詳細的鏈接 – 2011-04-15 09:49:36

+0

@gaearon - 答案現在更新... ......如果條件 – 2011-04-15 09:52:34

2

你可以鏈方法:

public void test(bool flag) 
{ 
    var res = employee.Where(x => x.EmployeeName = "Jhom"); 

    if (flag) 
    { 
     res = res.Where(x => x.EmployeeDepartment == "IT") 
    } 

    var id = res.Select(x => x.EmployeeID); 
} 
+0

我不明白爲什麼downvote?也許一個解釋可以幫助我改進我的答案? – mathieu 2011-04-15 09:42:49

+0

我相信這不是被問到的。問題不是未知的財產名稱,但未知(我可以這麼稱呼)'連鎖性'。您的回答並不能反映您如何使用動態LINQ鏈接查詢。更重要的是,你的例子是錯誤的,因爲'EmployeeName'不是'Employee'的屬性,它是一個傳遞給'Field'方法的字符串。 – 2011-04-15 09:49:41

+0

而最後但可能是downvote的主要原因,是我的主觀看法,這是一個壞主意。問題**不要求動態LINQ **,所需的只是任意的鏈接,這已經可以使用顯式的LINQ方法調用。只有在類型安全性難以達到的情況下(例如用戶在搜索框中輸入複雜表達式),纔會引入動態代碼而不是類型安全代碼。 **動態LINQ比解析更好,但比類型安全查詢更糟糕,這個問題很可能甚至是可取的。** – 2011-04-15 09:51:27

0
from e in employee  
where e.Field<string>("EmployeeName") == "Jhom" && 
(!flag || e.Field<string>("EmployeeDepartment") == "IT") 
select e.Field<string>("EmployeeID") 
0

您可以顯式調用LINQ方法並有條件地鏈接它們。

public IEnumerable<string> FilterEmployees (IEnumerable<Employee> source, bool restrictDepartment) 
{ 
    var query = source.Where (e => e.Field<string>("EmployeeName") == "Jhom"); 

    if (restrictDepartment) // btw, there's no need for "== true" 
     query = query.Where (e => e.Field<string>("EmployeeDepartment") == "IT"); 

    return query.Select (e => e.Field<string>("EmployeeID")); 
}