【问题标题】:Nullable object must have a value - why?可空对象必须有一个值 - 为什么?
【发布时间】:2012-04-18 09:56:23
【问题描述】:

我有以下 LINQ 查询

from p in dc.Purchases
where invoiceNumber == null || p.InvNumber == invoiceNumber.Value
select p;

'invoiceNumber' 是一个可为 null 的 int - 当它为 null 时,程序会抛出一个 'Nullable object must have a value error'。当它首先明确检查它是否为空时,为什么会这样?有没有办法解决这个问题?

谢谢,

【问题讨论】:

  • 把空检查改成invoiceNumber.HasValue有什么区别吗?
  • 您使用的是什么 Linq 提供程序? linq to sql、实体框架、linq to objects ... ?
  • LINQ to SQL。使用 HasValue 时没有区别
  • 只是猜测,但可能是 || 的顺序评估,如果您尝试 p.InvNumber == invoiceNumber.Value || 会发生什么invoiceNumber == null ?
  • 如果将 'p.InvNumber == invoiceNumber.Value' 替换为 'p.InvNumber == invoiceNumber' 会发生这种情况吗?

标签: c# linq linq-to-sql


【解决方案1】:

我认为您的查询有问题。根据您提供的代码,我假设 invoiceNumber 是局部变量或参数。如果是这种情况,那么您为什么还要在查询中检查 invoiceNumber == null ?此类检查应与查询分开进行:

if(invoiceNumber == null)
{
    return dc.Purchases; 
    // the query would evaluate to this because invoiceNumber == null will allways return true.
}
else
{
    return 
        from p in dc.Purchases 
        where p.InvNumber == invoiceNumber.Value
        select p;
}

【讨论】:

    【解决方案2】:

    试试这个:

    from p in dc.Purchases
    where invoiceNumber == null ||(invoiceNumber!=null && p.InvNumber == invoiceNumber.Value)
    select p;
    

    【讨论】:

    • 没有意义 - ||只有当第一个参数的计算结果为 false 时,运算符才会计算它的第二个参数
    • 不在 LINQ-to-SQL 中。查询被翻译成 SQL 并计算表达式的所有术语。没有短路,就像在 C# 中一样。使用空合并运算符 ?? (像 ISNULL 一样工作)或使用当值为 null 时评估为 false 的正常 SQL null 行为:where p.InvNumber == invoiceNumber。或者,当 invoiceNumber 不为空时,添加单独的 .Where() 条件。
    【解决方案3】:

    检查这个

    from p in dc.Purchases
    where (invoiceNumber == null ? p.InvNumber == null : p.InvNumber == invoiceNumber.Value)
    select p;
    

    【讨论】:

      【解决方案4】:

      怎么样

      from p in dc.Purchases 
      where (invoiceNumber ?? p.InvNumber) == p.InvNumber
      select p;
      

      但是,我会提出一个问题,如果 invoiceNumbernull,为什么要运行此语句?

      【讨论】:

      • 如果它为空,它应该检索所有内容
      • @Chris,所以,另一个没有 where 子句的语句会更有效地执行您的数据库。
      【解决方案5】:

      使用 HasValue 属性检查 Nullable 是否具有值。

      from p in dc.Purchases
      where !invoiceNumber.HasValue || p.InvNumber == invoiceNumber.Value
      select p;
      

      【讨论】:

        【解决方案6】:

        你不知道,但我怀疑p.InvNumber 也可以为空。在这种情况下,不要使用.Value

        from p in dc.Purchases
        where invoiceNumber == null || p.InvNumber == invoiceNumber
        select p;
        

        【讨论】:

          【解决方案7】:

          您不需要明确检查 null。 可空值可能有两种情况,要么为空,要么具有某些值。

          例如

          案例 1-

           int ? invoiceNumber = null;
           var prods = from p in dc.Purchases 
                       where p.InvNumber == invoiceNumber
                       select p;
          

          案例2-

           int ? invoiceNumber = 100;
           var prods = from p in dc.Purchases 
                       where p.InvNumber == invoiceNumber
                       select p;
          

          相同的 linq 语句适用于这两种情况。

          【讨论】:

          • 为什么案例1有where子句?
          • 我只想描述相同的 linq 查询在这两种情况下都可以工作。 invoiceNumber 为 null 或具有某些值。
          【解决方案8】:

          问题可能出在 Linq-to-Sql 中 - 它正在尝试将 where 语句转换为 SQL,因此即使为 null 也可以调用 invoiceNumber.Value。

          请尝试invoiceNumber == null || p.InvNumber == invoiceNumber

          希望对你有所帮助。

          【讨论】:

            【解决方案9】:

            nullable 类型的基本概念是......底层类型将具有在其范围内指定的所有值 + null 值,以增加数据库编程的灵活性。

            可空类型有两个只读属性 1) HasValue 2) Value

            HasValueboolean 类型,如果 Value 中有某个值,它会自动设置为 true。 因此,为了进行比较,您必须先使用HasValue,然后再使用Value。如果直接使用Value,如果是null,则会抛出上述异常。

            记住这些,我也怀疑这个片段。 invoiceNumber == null 你应该试试invoiceNumber.Value==null(不是invoiceNumber)

            where invoiceNumber.HasValue && p.InvNumber == invoiceNumber.Value 
            

            谢谢

            【讨论】:

              猜你喜欢
              • 2010-12-26
              • 2012-02-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-05-20
              相关资源
              最近更新 更多