linq where子句中的空值

时间:2017-05-05 13:34:03

标签: c# linq

我遇到了一个问题,我想在某些内容匹配的情况下返回结果,如果我尝试匹配的其中一个属性为空,则会出现错误。

  if (!string.IsNullOrEmpty(searchString))
  {
      Infos = Infos.Where(
          x =>
          x.FirstName.ToLower().Contains(searchString) ||
          x.LastName.ToLower().Contains(searchString) ||
          x.ContractNum.ToLower().Contains(searchString) ||
          x.VIN.ToLower().Contains(searchString) ||
          x.Claim.InitiatedBy.ToLower().Contains(searchString)
          ).ToList();
  }

例如,如果ContractNumVIN为null,则会引发错误。我不确定如何在linq查询中检查其中一个是否为null。

6 个答案:

答案 0 :(得分:5)

您可以添加显式空检查:

  Infos = Infos.Where(
      x =>
      (x.FirstName != null   && x.FirstName.ToLower().Contains(searchString)) ||
      (x.LastName != null    && x.LastName.ToLower().Contains(searchString)) ||
      (x.ContractNum != null && x.ContractNum.ToLower().Contains(searchString)) ||
      (x.VIN != null         && x.VIN.ToLower().Contains(searchString)) ||
      (x.Claim != null       && x.Claim.InitiatedBy != null && x.Claim.InitiatedBy.ToLower().Contains(searchString))
      ).ToList();

答案 1 :(得分:4)

您有多个选项,第一个是对null进行显式检查,另一个选项是使用Null传播运算符。

x.FirstName != null &&  x.FirstName.ToLower().Contains(searchString)

x.FirstName?.ToLower()?.Contains(searchString) == true

但我建议您使用IndexOf代替Contains 不敏感的比较。

类似的东西:

x.FirstName?.IndexOf(searchString, StringComparison.CurrentCultureIgnoreCase) >= 0)

答案 2 :(得分:2)

在比较之前检查属性为null或为空它是我知道的唯一方法

if (!string.IsNullOrEmpty(searchString))
      {
          Infos = Infos.Where(
              x =>
              (!String.IsNullOrEmpty(x.FirstName) && x.FirstName.ToLowerInvariant().Contains(searchString)) ||
              (!String.IsNullOrEmpty(x.LastName) && x.LastName.ToLowerInvariant().Contains(searchString)) ||
              (!String.IsNullOrEmpty(x.ContractNum) && x.ContractNum.ToLowerInvariant().Contains(searchString)) ||
              (!String.IsNullOrEmpty(x.VIN) && x.VIN.ToLowerInvariant().Contains(searchString)) ||
              (x.Claim != null && !String.IsNullOrEmpty(x.Claim.InitiatedBy) && x.Claim.InitiatedBy.ToLowerInvariant().Contains(searchString))
              ).ToList();
      }

额外:我在Claim属性上添加了一项检查,以确保在查看InitiatedBy

时它不为空

EXTRA 2:使用内置函数IsNullOrEmpty将字符串与""null进行比较,以便代码更清晰。

额外3:用于ToLowerInvarianthttps://msdn.microsoft.com/en-us/library/system.string.tolowerinvariant(v=vs.110).aspx),因此无论文化如何,降低行动都会起作用。

答案 3 :(得分:1)

您可以使用??将其替换为可接受的值。

   (x.ContractNum??"").ToLower()

答案 4 :(得分:1)

我会使用null条件运算符?,然而,这将返回一个可为空的bool?,因此您需要适当地处理它。

有关如何执行此操作的一些示例:

x?.FirstName?.ToLower().Contains(searchString) == true;
x?.FirstName?.ToLower().Contains(searchString) ?? false;

答案 5 :(得分:1)

另一种方法是将比较逻辑保留在一个地方以使用属性的子集合并检查它们:

Infos = Infos.Where(i=> 
   new[] {i.FirstName,i.LastName,i.ContractNum /*etc*/}
   .Any(w=> w?.ToLower().Contains(searchString) ?? false))
   .ToList();

(它确实读出了所有属性,但这不应该花费很多性能并且可以获得很高的可维护性)