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

时间:2014-01-22 15:37:48

标签: c# entity-framework linq-to-entities

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

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

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

contacts = contacts.Where(s => s.firstname.ToUpper().Contains(fNameSearch.ToUpper() ?? *)

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

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

 contacts = contacts.Where(s => s.firstname.ToUpper().Contains(fNameSearch.ToUpper() ?? "test")

但我希望能够归还所有东西,而不仅仅是“测试”。

2 个答案:

答案 0 :(得分:8)

  

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

fNameSearch.ToUpper() ?? *

你的信念是错误的。只有在左侧可能为空时才使用??才有意义。如果fNameSearch为null,则调用ToUpper()会抛出;如果它不为null,则对ToUpper()的调用产生非空字符串。因此,??运算符不是您想要使用的。

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

fNameSearch.?ToUpper() ?? "test"

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

不幸的是,C#中不存在.?运算符。这是一个经常被请求的功能,因此该语言的未来版本可能会有它。

  

但我希望能够归还所有东西,而不仅仅是“测试”。

然后你不想要任何一个算子。

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

  • 如果fNameSearch为null,则匹配所有内容
  • 否则,请匹配firstName.ToUpper().Contains(fnameSearch.ToUpper)

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

s => fNameSearch == null || s.firstname.ToUpper().Contains(fNameSearch.ToUpper())

这段代码是否正确?

没有。 ToUpper不是标准化名称的好方法。请记住,名称是文化工件<​​/ em>,因此必须使用与名称相关联的文化的正确规则进行搜索。

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

culture.CompareInfo.IndexOf(firstname, fNameSearch, CompareOptions.IgnoreCase) 

并查看它是否带有有效索引。

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

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

答案 1 :(得分:6)

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

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

编辑:根据Steve的评论,区分大小写取决于数据库的整理(并且是case-insensitive by default),因此您只需运行:

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

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