LINQ查询AND和OR

3

我开始学习.NET,需要一些帮助。

我将通过举例来描述我的情况,说明我有什么以及我需要做什么,但我不知道如何去做。

所以,我有一个像这样的类:

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

变量bansIQueryable类型。

在方法签名中:

public IEnumerable<Ban> FindBans(Ban filter);

我需要搜索那个bans变量;

我现在的搜索方式

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();
}

过滤器使用AND。SQL查询部分应如下所示:
... WHERE group_name = 'abc' AND nick = 'def' AND ip = 'ghi';

我需要的是:

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

所有这些都需要是动态的(如果我们不传递 GroupName,则不要按其进行过滤等)。 除手动使其动态外,我不知道如何实现。
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));
}

等等还有...现在向Ban中添加另一个变量。


尝试这样写:.Where((b => b.GroupName =="abc") && b.(nick =="def")||b.ip=="ghi") - Thirisangu Ramanathan
@Thirisangu:那无法处理空值情况,就像当前代码中一样。我认为 SQL 语句并不完全正确。 - Patrick Hofman
我认为PredicateBuilder可以帮助你。http://www.albahari.com/nutshell/predicatebuilder.aspx - Felipe Oriani
3个回答

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 )
                        )
                 );

如果 GroupName 为空,Nick 为空且 IP 是“1.1.1.1”,那么检查 IP 的部分甚至不会被评估。我认为这是因为它没有起作用。 - David Skuza
@user2825007:您确定吗?LINQ的Where是在枚举项时进行评估的,是吗? - Patrick Hofman
是的。http://i.imgur.com/qzKbkXn.png 在这种情况下,第一个(名称)为空,因此它将其评估为真,因此忽略OR语句的其余部分。 - David Skuza
@user2825007:这就是“或”操作的一般概念,对吧? - Patrick Hofman

1
你可以针对nick和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();
}

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接