2014-10-20 64 views
3

我开始与NET的旅程,我需要一点帮助。LINQ查询AND&OR

我会通过例子来描述我的情况,我有什么和我需要做什么,但我不知道该怎么做。

所以我有这样

public class Ban 
{ 
    public int ID { get; set; } 
    public string Nick { get; set; } 
    public string IP { get; set; } 
    public string GroupName { get; set; } 
} 

和可变禁令这是的IQueryable

然后在签名方法的类

public IEnumerable<Ban> FindBans(Ban filter); 

我需要通过搜索禁令变量;

我现在

public IEnumerable<Ban> FindBans(Ban filter) 
{ 
    var bans = GetBansQueryable(); 

    if (!string.IsNullOrWhiteSpace(filter.GroupName)) 
    { 
     bans = bans.Where(b => b.GroupName == filter.GroupName); 
    } 
    if (!string.IsNullOrWhiteSpace(filter.Nick)) 
    { 
     bans = bans.Where(b => b.Nick == filter.Nick); 
    } 
    if (!string.IsNullOrWhiteSpace(filter.IP)) 
    { 
     bans = bans.Where(b => b.IP == filter.IP); 
    } 

    return bans.AsEnumerable(); 
} 

与和过滤器进行搜索。 SQL查询部分会是这样

... WHERE group_name = 'abc' AND nick = 'def' AND ip = 'ghi'; 

我需要的是

... WHERE group_name = 'abc' AND (nick = 'def' OR ip = 'ghi'); 

所有这一切都必须是动态的(如果我们不通过组名不要被它过滤等。 ) 我不知道我怎么能做到这一点的旁边使这一动态manualy像

if (!string.IsNullOrWhiteSpace(filter.GroupName) && 
    string.IsNullOrWhiteSpace(filter.Nick) && 
    string.IsNullOrWhiteSpace(filter.IP)) 
{ 
    bans = bans.Where(b => b.GroupName == filter.GroupName); 
} 
else if (!string.IsNullOrWhiteSpace(filter.GroupName) && 
    !string.IsNullOrWhiteSpace(filter.Nick) && 
    string.IsNullOrWhiteSpace(filter.IP)) 
{ 
    bans = bans.Where(b => b.GroupName == filter.GroupName && b.Nick == filter.Nick); 
} 
else if (!string.IsNullOrWhiteSpace(filter.GroupName) && 
    !string.IsNullOrWhiteSpace(filter.Nick) && 
    !string.IsNullOrWhiteSpace(filter.IP)) 
{ 
    bans = bans.Where(b => b.GroupName == filter.GroupName && (b.Nick == filter.Nick || b.IP == filter.IP)); 
} 

等等...现在再添变数取缔。

+0

试试这个:'。凡((B => b.GroupName == “ABC”)&&湾(nick ==“def”)|| b.ip ==“ghi”)' – 2014-10-20 11:21:26

+0

@Thirisangu:那不处理空例,就像在当前代码中一样。我认为SQL语句不完全正确。 – 2014-10-20 11:22:22

+0

我认为PredicateBuilder可以帮到你。 http://www.albahari.com/nutshell/predicatebuilder.aspx – 2014-10-20 11:36:45

回答

1

我认为你可以简化你这样整个约束:

bans = bans.Where(b => (string.IsNullOrWhiteSpace(filter.GroupName) || b.GroupName == filter.GroupName) 
         && 
         ((string.IsNullOrWhiteSpace(filter.Nick) || b.Nick == filter.Nick) 
          || 
          (string.IsNullOrWhiteSpace(filter.IP) || b.IP == filter.IP) 
         ) 
       ); 
+0

如果GroupName为空,Nick为空,IP为“1.1.1.1”,那么检查IP的部分甚至不会被评估。我想,因为它不起作用。 – 2014-10-20 11:43:48

+0

@ user2825007:你确定。 LINQ当Where枚举项目时评估Where,right。 – 2014-10-20 11:45:43

+0

是的。 http://i.imgur.com/qzKbkXn。png第一个(本例中的Name)是空的,因此它将其评估为true,因此它忽略OR语句的其余部分。 – 2014-10-20 12:09:06

1

你可以特殊情况下都尼克和IP已知的情况:

public IEnumerable<Ban> FindBans(Ban filter) 
{ 
    var bans = GetBansQueryable(); 

    if (!string.IsNullOrWhiteSpace(filter.GroupName)) 
    { 
     bans = bans.Where(b => b.GroupName == filter.GroupName); 
    } 

    if (!string.IsNullOrWhiteSpace(filter.Nick) && !string.IsNullOrWhiteSpace(filter.IP)) 
    { 
     bans = bans.Where(b => b.Nick == filter.Nick || b.IP == filter.IP); 
    } 
    else if (!string.IsNullOrWhiteSpace(filter.Nick)) 
    { 
     // filter.IP is empty 
     bans = bans.Where(b => b.Nick == filter.Nick); 
    } 
    else if (!string.IsNullOrWhiteSpace(filter.IP)) 
    { 
     // filter.Nick is empty 
     bans = bans.Where(b => b.IP == filter.IP); 
    } 

    return bans.AsEnumerable(); 
}