2010-11-18 75 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