2010-11-18 71 views
2

我有一個包含「commands」和「states」的數據庫表。每個命令可以有多個狀態,用戶可以在搜索時對其進行配置。例如,命令可以是「運行」,它可以有兩種狀態:「快速」和「慢速」。使用linq-to-sql幫助進行高級數據庫搜索

我想用「Fast」或「Slow」在我的表格中搜索名爲「Run」的所有命令。這是很簡單的事:

var results = from t in table 
       where t.Command == "Run" && 
       (t.State == "Fast" || t.State == "Slow") 
       return t; 

但是用戶也可以搜索命令「走」與國家「快」,所以查詢看起來像:

var results = from t in table 
        where (t.Command == "Run" && 
         (t.State == "Fast" || t.State == "Slow")) || 
        (t.Command == "Walk" && 
        t.State == "Fast") 
        return t; 

有一個潛在的儘可能多的搜索這樣,我想知道如何將它們合併成一個循環。

我不能做到這一點:

foreach(var command in commands) 
{ 
    foreach(var state in command.states) 
    { 
     results = from t in table 
        where t.Command == command.Command && 
        t.State == state; 
    } 
} 

,因爲一旦它搜索「運行」,「走」將被排除在外結果,這樣要求的「走」會導致沒有成績可言。

有沒有人知道一個很好的方法來做到這一點?

回答

7

使用喬阿爾巴哈利的PredicateBuilder建立一個謂語:

var predicate = PredicateBuilder.False<Entry>(); 
foreach(var command in commands) 
{ 
    foreach(var state in command.states) 
    { 
     predicate = predicate.Or(p => p.Command == command.Command && p.State == state); 
    } 
} 
var query = table.Where(predicate); 

還是更LINQ重版本:

var commandStates = from c in commands 
        from s in c.states 
        select new {c.Command, State = s}; 
var predicate = commandStates.Aggregate(
    PredicateBuilder.False<Entry>(), 
    (pred, e) => pred.Or(p => p.Command == e.Command && p.State == e.state)); 
var query = table.Where(predicate); 
+0

+1易如反掌 - 幾乎:) – 2010-11-18 16:32:46

+0

這是非常及時的實際(謂語建築師),因爲我已經蹣跚了一會兒聚集在哪裏子句 - 很好找。你的成功如何順應它? – 2010-11-18 16:39:33

+0

@jim:我其實還沒有需要它。我們所做的大部分工作要麼簡單到不需要它,要麼足夠先進,無論如何我都必須手動構建整個表達式樹。如果你使用的是PredicateBuilder,你可能希望一般來看LinqKit。它有一些方便的功能來調用謂詞和事物。 – StriplingWarrior 2010-11-18 17:14:49