【问题标题】:LINQ Where Clause BehaviorLINQ Where 子句行为
【发布时间】:2014-05-05 18:51:03
【问题描述】:

我正在尝试编写一个搜索例程,其中一部分包含以下代码:

string searchValue = Server.HtmlEncode(RadSearchBox.Text.ToLower());

var injurySearchList = (from i in injuryObj
                        where i.IsDeleted == false &&
                        (
                            i.ResultOther == true ? "ResultOther".ToLower().Contains(searchValue) : i.IncidentID.ToString().Contains(searchValue)
                            || i.BodyPartHead == true ? "BodyPartHead".ToLower().Contains(searchValue) : i.IncidentID.ToString().Contains(searchValue)
                        )
                        select i.IncidentID).ToList();

由于我无法搜索字符串的位值,因此我使用三元运算符来评估它是否为真。如果是这样,我 [手动] 将字段名称转换为字符串,并查看其中是否包含搜索字符串。如果位值为假,我宁愿从 WHERE 子句中排除该行,但无法提出任何聪明的想法,因此我使用了将 IncidentID 字段转换为带有 Contains() 方法的字符串作为填充物。

以如下数据集为例:

+------------+-------------+--------------+-----------+
| IncidentID | ResultOther | BodyPartHead | IsDeleted |
+------------+-------------+--------------+-----------+
|          1 |           0 |            1 |         0 |
|          2 |           1 |            1 |         0 |
|          3 |           0 |            1 |         0 |
+------------+-------------+--------------+-----------+

问题是当 searchValue 等于“body”时,它只返回 IncidentID 1 和 3,但 2 也应该在其中。相反,如果 searchValue 等于“结果”,它只返回 IncidentID 2,如预期的那样。

有什么想法吗?

【问题讨论】:

    标签: c# asp.net linq search


    【解决方案1】:

    您遇到了操作顺序问题。 OR (||) 在条件三元运算符之前进行评估。您需要用括号将两个 OR 操作括起来:

    where i.IsDeleted == false &&
    (
        (i.ResultOther == true ? "ResultOther".ToLower().Contains(searchValue) : i.IncidentID.ToString().Contains(searchValue))
        || (i.BodyPartHead == true ? "BodyPartHead".ToLower().Contains(searchValue) : i.IncidentID.ToString().Contains(searchValue))
    )
    

    你原来的代码相当于:

    where i.IsDeleted == false &&
    (
        i.ResultOther == true 
            ? "ResultOther".ToLower().Contains(searchValue) 
            : (i.IncidentID.ToString().Contains(searchValue)) || (i.BodyPartHead == true)
                  ? "BodyPartHead".ToLower().Contains(searchValue) 
                  : i.IncidentID.ToString().Contains(searchValue))
    )
    

    (你也可以去掉== true并使用!而不是== false,但这些不会改变结果,只是表面上的改变)

    【讨论】:

    • 不客气。顺便说一句,您接受的答案不是第一个(我不在乎您接受哪个,只是确保您使用正确的标准)。
    • 我不喜欢每个名字上方的“回答 ## 分钟前”的说法。在哪里可以找到日期/时间戳?
    • 将鼠标悬停在“已回答”之后的标签上。没什么大不了的(我真的不是想让你改变你接受的答案)——只是指出来。
    • 我力求准确,我的意图是/是将它授予第一个/正确的解决方案,因此它已按预期重新应用。感谢您的解决方案和教育,D!
    【解决方案2】:

    我相信您需要围绕内部 ? : 语句进行解释,如下所示:

    var injurySearchList = (from i in injuryObj
                            where i.IsDeleted == false &&
                            (
                                (i.ResultOther == true
                                     ? "ResultOther".ToLower().Contains(searchValue)
                                     : i.IncidentID.ToString().Contains(searchValue))
                             || (i.BodyPartHead == true
                                     ? "BodyPartHead".ToLower().Contains(searchValue)
                                     : i.IncidentID.ToString().Contains(searchValue))
                                )
                            select i.IncidentID).ToList();
    

    从你描述你真正想要完成的事情来看,我认为下面的简化会给你同样的结果:

    var injurySearchList2 = (from i in injuryObj
                             where !i.IsDeleted 
                             && (
                                 (i.ResultOther && "resultother".Contains(searchValue))
                              || (i.BodyPartHead  && "bodyparthead".Contains(searchValue))
                             )
                             select i.IncidentID).ToList();
    

    【讨论】:

    • 也是正确的答案,感谢您的简化,效果更好。我会对此投赞成票,但还没有代表。
    【解决方案3】:

    您需要在这两个条件周围加上括号。第二个被第一个包裹起来,像这样:

    where i.IsDeleted == false &&
    (
        i.ResultOther == true ? "ResultOther".ToLower().Contains(searchValue) : (i.IncidentID.ToString().Contains(searchValue) || i.BodyPartHead == true ?  "BodyPartHead".ToLower().Contains(searchValue) : i.IncidentID.ToString().Contains(searchValue))
    )
    

    应该是:

    where i.IsDeleted == false &&
    (
        (i.ResultOther == true ? "ResultOther".ToLower().Contains(searchValue) : i.IncidentID.ToString().Contains(searchValue))
        || (i.BodyPartHead == true ?  "BodyPartHead".ToLower().Contains(searchValue) : i.IncidentID.ToString().Contains(searchValue))
    )
    

    【讨论】:

    • 就是这样。其他答案效果很好,但你是第一个。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2010-10-10
    • 2021-02-02
    • 2021-07-05
    相关资源
    最近更新 更多