【问题标题】:LINQ to SQL and Null strings, how do I use Contains?LINQ to SQL 和 Null 字符串,如何使用包含?
【发布时间】:2009-06-10 17:49:19
【问题描述】:

这里是查询

from a in this._addresses
where a.Street.Contains(street) || a.StreetAdditional.Contains(streetAdditional)
select a).ToList<Address>()

如果 where 子句中的两个属性都有值,这可以正常工作,但如果例如 a.StreetAdditional 为空(大多数情况下),我将得到空引用异常。

有解决办法吗?

谢谢,

【问题讨论】:

  • 您遇到异常了吗?还是您在推测可能有异常?
  • 如果你有一个NullReferenceException,你就没有在做 LINQ to SQL 查询。
  • 您也可以考虑不允许 Street 或 StreetAdditional 为空。如果您的数据库支持默认值,您可以将它们默认为空字符串,设置标志以禁止空值并避免需要空值检查。
  • 附带说明,该查询在 LinqPad 中确实有效。这怎么可能?为什么这两种工具的 Linq to SQL 行为会有如此大的差异?

标签: c# .net linq-to-sql


【解决方案1】:

我会使用空合并运算符...

(from a in this._addresses
where (a.Street ?? "").Contains(street) || (a.StreetAdditional ?? "").Contains(streetAdditional)
select a).ToList<Address>()

【讨论】:

  • 这是一种更简洁的方法。非常适合处理 IQueryable
【解决方案2】:

最明显的一个:

from a in this._addresses
where (a.Street != null && a.Street.Contains(street)) || (a.StreetAdditional != null && a.StreetAdditional.Contains(streetAdditional))
select a).ToList<Address>()

或者,您可以为 Contains 编写一个扩展方法,该方法接受 null 参数而不会出错。有人可能会说,拥有这样的方法并不那么漂亮,因为它看起来像一个普通的方法调用,但允许为 null 值(从而搁置了正常的 null 检查实践)。

【讨论】:

  • 自定义扩展方法在 LINQ to SQL 中不可用。
【解决方案3】:

您必须先检查StreetAdditional 是否为null

试试

where a.Street.Contains(street) || ((a != null) && a.StreetAdditional.Contains(streetAdditional))

这是可行的,因为&amp;&amp; 是一个快捷方式操作符,如果a != null 的结果为false,则不会计算具有null 值的第二个表达式,因为结果将为@ 987654327@反正。

【讨论】:

    【解决方案4】:

    我会创建一个扩展方法,如果为 null,则返回一个空序列,然后调用 contains 方法。

    public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> pSeq)
    {
          return pSeq ?? Enumerable.Empty<T>();
    }
    
    from a in this._addresses
    where a.Street.Contains(street) || 
          a.StreetAdditional.EmptyIfNull().Contains(streetAdditional)
    select a).ToList<Address>()
    

    【讨论】:

    • 看起来有点奇怪,因为null-objects 似乎能够调用成员函数。
    • 赞成使用 ??操作员。这也是我的建议。如果您觉得扩展方法使查询看起来很奇怪,您可以不使用扩展方法。
    【解决方案5】:

    我不认为 SqlServer 给了你一个空异常。如果是这样,那么这段代码显然没有通过 LinqToSql 运行(正如你标记的问题)。

    string.Contains 会被翻译成 sql 的like,对于 null 值完全没有问题。

    【讨论】:

      【解决方案6】:

      检查以确保属性不为空

      from a in this._addresses
      where (a.Street != null && a.Street.Contains(street)) || 
      (a.StreetAdditional != null && a.StreetAdditional.Contains(streetAdditional))
      select a).ToList<Address>()
      

      如果空检查为假,则 && 之后的第二个子句将不计算。

      【讨论】:

        【解决方案7】:
        from a in this._addresses
        where a.Street.Contains(street) || (a.StreetAdditional != null && a.StreetAdditional.Contains(streetAdditional)
        select a).ToList<Address>()
        

        【讨论】:

          【解决方案8】:

          您可能需要检查以确保变量 street 和 streetAdditional 不为空。我刚刚遇到了同样的问题,将它们设置为空字符串似乎可以解决我的问题。

          street = street ?? "";
          streetAdditional = streetAdditional ?? "";
          from a in this._addresses
          where a.Street.Contains(street) || a.StreetAdditional.Contains(streetAdditional)
          select a).ToList<Address>()
          

          【讨论】:

            【解决方案9】:

            需要注意的一点是,应首先评估 null。

            where (**a.Street != null** && a.Street.Contains(street)) || (a.StreetAdditional != null && a.StreetAdditional.Contains(streetAdditional))
            select a).ToList<Address>
            

            ()

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多