使用可选搜索子句执行 LINQ 查询

发布于 2024-09-10 09:09:08 字数 616 浏览 4 评论 0原文

我有一个页面,您可以在其中搜索人员。他们可以获取所有人的列表,也可以按某些标准(例如名字或姓氏)对其进行过滤。

到目前为止,我一直在尝试使用这个问题中详细介绍的技术。

因此,我的代码看起来像是

string firstname=...
string lastname=...

var people=from p in People.All()
           where (firstname==null || firstname.ToLower()==p.FirstName.ToLower()) &&
                 (lastname==null || lastname.ToLower()==p.LastName.ToLower())
           select p;

在构建查询时遇到空引用错误,但是当名字和姓氏都为空时。删除 where 子句可以消除错误。

为什么这行不通? C# 是否尝试计算 where 子句每个部分的第二部分?应该不是因为短路或者吧?

I have a page where you can search for people. They can either get a list of all people, or filter it by certain criteria such as first or last name.

So far, I have been trying trying to use the technique detailed in this question.

So my code looks like

string firstname=...
string lastname=...

var people=from p in People.All()
           where (firstname==null || firstname.ToLower()==p.FirstName.ToLower()) &&
                 (lastname==null || lastname.ToLower()==p.LastName.ToLower())
           select p;

I get a null reference error when building the query however when both firstname and lastname is null. Removing the where clause gets rid of the error.

Why would this not work? Does C# try to evaluate the second part of each part of the where clause? It shouldn't because of the short-circuited OR right?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

魂ガ小子 2024-09-17 09:09:08

使用 string.Equals:

from p in People.All()
where (firstname == null || string.Equals (firstname, p.FirstName, StringComparison.InvariantCultureIgnoreCase)) &&
      (lastname == null || string.Equals (lastname, p.LastName, StringComparison.InvariantCultureIgnoreCase))
select p

这不仅避免了 null 问题,而且还强制您指定字符串比较类型(这是一件好事)。换句话说,您指定在执行不区分大小写的比较时是否使用特定于本地区域性或固定区域性的规则。

Use string.Equals:

from p in People.All()
where (firstname == null || string.Equals (firstname, p.FirstName, StringComparison.InvariantCultureIgnoreCase)) &&
      (lastname == null || string.Equals (lastname, p.LastName, StringComparison.InvariantCultureIgnoreCase))
select p

Not only does this avoid the null problem, but it forces you to specify a string comparison type (a good thing). In other words, you specify whether to use rules specific to the local or invariant culture when performing the case-insensitive comparison.

浮萍、无处依 2024-09-17 09:09:08

您不需要调用 ToLower() 使用 string.compare 代替ignoreCase

string.Compare(firstName, p.FirstName, true) 

you don't need to call ToLower() use string.compare instead with ignoreCase

string.Compare(firstName, p.FirstName, true) 
莳間冲淡了誓言ζ 2024-09-17 09:09:08

在调用 ToLower 之前确保它不为 null:

(firstname==null || (firstname!= null && firstname.ToLower()==p.FirstName.ToLower()))

Make sure it's not null before calling the ToLower:

(firstname==null || (firstname!= null && firstname.ToLower()==p.FirstName.ToLower()))
把时间冻结 2024-09-17 09:09:08

当两者都为 null 时它不起作用,因为语句的第一部分将计算为 true,不允许短路计算。为什么不使用等价规则来翻转语句呢?

(firstName != null && firstName.ToLower() == p.firstName.ToLower()) 

编辑:我编写了以下内容并在 LINQPad 4 中成功运行它,没有任何问题。我假设对 People.All() 的调用只是返回一个包含完整记录集的 IQueryable ?也许可以在此处发布您的异常文本,以便我们可以查看您是否无意中错过了某些内容?

void Main()
{
    string a = null;
    string b = null;
    var peeps = new List<Person> { 
        new Person { 
            FirstName = "John",
            LastName = "Connor"
        },
        new Person { 
            FirstName = "Sarah",
            LastName = "Connor",
        },
        new Person { 
            FirstName = "Cletus",
            LastName = "Handy"
        }
    };

    var somePeeps = from p in peeps
        where (a == null || a.ToLower() == p.FirstName.ToLower()) 
            && (b == null || b.ToLower() == p.LastName.ToLower())
        select p;

    somePeeps.Dump();

}

public class Person
{
    public string FirstName { get; set;}
    public string LastName { get; set;}
}

It doesn't work when both are null because the first part of the statement will evaluate to true, disallowing short-circuiting of the evaluation. Why not use equivalency rules to flip the statement?

(firstName != null && firstName.ToLower() == p.firstName.ToLower()) 

EDIT: I wrote the following up and ran it successfully in LINQPad 4, with no issues. I'm assuming that the call to People.All() simply returns an IQueryable<People> with the full set of records? Maybe post your exception text here so we can see if there's something you've inadvertently missed?

void Main()
{
    string a = null;
    string b = null;
    var peeps = new List<Person> { 
        new Person { 
            FirstName = "John",
            LastName = "Connor"
        },
        new Person { 
            FirstName = "Sarah",
            LastName = "Connor",
        },
        new Person { 
            FirstName = "Cletus",
            LastName = "Handy"
        }
    };

    var somePeeps = from p in peeps
        where (a == null || a.ToLower() == p.FirstName.ToLower()) 
            && (b == null || b.ToLower() == p.LastName.ToLower())
        select p;

    somePeeps.Dump();

}

public class Person
{
    public string FirstName { get; set;}
    public string LastName { get; set;}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文