在lambda表达式中使用通配符的null-coalescing运算符

tin*_*han 2 c# linq-to-entities entity-framework

我有一个包含多个输入的搜索表单 - 名字,姓氏,公司......

我想根据用户输入返回实体,或者如果没有输入任何内容,例如在姓氏字段中,则返回所有姓氏.

我相信我应该为此使用null-coalescing,就像t-sql中的"ISNULL"...

contacts = contacts.Where(s => s.firstname.ToUpper().Contains(fNameSearch.ToUpper() ?? *)
Run Code Online (Sandbox Code Playgroud)

问题是我不知道如何在这种类型的预测中使用通配符.

例如,如果fNameSearch为null或white-space,则返回firstname属性中包含"test"的所有内容...

 contacts = contacts.Where(s => s.firstname.ToUpper().Contains(fNameSearch.ToUpper() ?? "test")
Run Code Online (Sandbox Code Playgroud)

但我希望能够归还所有东西,而不仅仅是"测试".

Eri*_*ert 8

我相信我应该使用null-coalescing:

fNameSearch.ToUpper() ?? *
Run Code Online (Sandbox Code Playgroud)

你的信念是错误的.只有??当左侧可能为空时才使用它是有意义的.如果fNameSearch为null则调用ToUpper()throws; 如果它不为null,则调用ToUpper()生成非空字符串.所以??操作员不是你想要使用的.

您正在寻找的运营商是提升的可空成员访问运营商:

fNameSearch.?ToUpper() ?? "test"
Run Code Online (Sandbox Code Playgroud)

这意味着"如果fNameSearch为null则生成null,将其提供给??运算符并获取"test";如果它不为null则调用ToUpper(),这将生成非空字符串.

不幸的.?是,C#中不存在运算符.这是一个经常被要求的功能,所以也许该语言的未来版本将拥有它.

但我希望能够归还所有东西,而不仅仅是"测试".

那你不需要任何一个算子.

退后一步.陈述你想要谓词的行为.

  • if fNameSearch为null然后匹配所有内容
  • 否则,匹配 firstName.ToUpper().Contains(fnameSearch.ToUpper)

好的,这是一个容易编写的谓词.

s => fNameSearch == null || s.firstname.ToUpper().Contains(fNameSearch.ToUpper())
Run Code Online (Sandbox Code Playgroud)

那么这段代码是否正确?

ToUpper是不是规范化名的好方法.请记住,名称是文化工件,因此必须使用与名称相关联的文化的正确规则进行搜索.

执行此操作的正确方法是获取CultureInfo写入名称的文化对象,然后调用

culture.CompareInfo.IndexOf(firstname, fNameSearch, CompareOptions.IgnoreCase) 
Run Code Online (Sandbox Code Playgroud)

并查看它是否返回有效索引.

此外,在编写更多试图规范化名称的代码之前,您可能应该阅读本文.

http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/

  • @EthanPelton:纯文字格式容易误读简洁 - 这是一件好事 - 对于粗鲁或粗鲁; 无意.我建议你首先要学会更多地阅读慈善事业,其次,当你发布一堆错误,破损的代码并寻求帮助时,期望得到一份简明的错误列表和改进方法的建议.而且:在我回答之前,问题没有得到彻底的回答*; 我的答案是唯一正确描述如何进行不区分大小写的文化比较的答案. (3认同)

Dou*_*las 6

如果要返回所有内容,是否可以在查询之前放置条件?

var contacts = /* construct your original query here */
if (fNameSearch != null)
    contacts = contacts.Where(s => s.firstname.ToUpper().Contains(fNameSearch.ToUpper());
Run Code Online (Sandbox Code Playgroud)

编辑:根据Steve的评论如下,区分大小写取决于数据库的排序规则(默认情况下不区分大小写),因此您可以运行:

var contacts = /* construct your original query here */
if (fNameSearch != null)
    contacts = contacts.Where(s => s.firstname.Contains(fNameSearch));
Run Code Online (Sandbox Code Playgroud)

编辑2:如果要检查多个输入,则可以使用相同的方法:

var contacts = /* construct your original query here */
if (string.IsNullOrEmpty(fNameSearch) == false))
    contacts = contacts.Where(s => s.firstname.Contains(fNameSearch));
if (string.IsNullOrEmpty(fSurnameSearch) == false))
    contacts = contacts.Where(s => s.surname.Contains(fSurnameSearch));
if (string.IsNullOrEmpty(fCompanySearch) == false))
    contacts = contacts.Where(s => s.company.Contains(fCompanySearch));
Run Code Online (Sandbox Code Playgroud)