【问题标题】:Nullable Object must have a value #2可空对象必须有一个值 #2
【发布时间】:2012-02-03 16:05:44
【问题描述】:

我正在尝试重用我一直使用的相同代码,但现在遇到了错误。

我正在遍历各种用户表,并在其中执行以下操作:

DateTime dcdt = (DateTime)u.DateCreated;
DateTime lldt = (DateTime)u.LastLogon;
userRow["DateCreated"] = dcdt.ToShortDateString();

在循环内。我得到了错误:

System.InvalidOperationException: Nullable object must have a value.

错误突出显示“lldt”行,而不是首先出现的“dcdt”。这本身就很奇怪。检查数据库中的这两个字段“允许空值”。它们都可以为空,也可以都不为空。

这两个值都被列为日期时间?通过智能感知类型。

我不明白为什么 ASP.NET 拒绝让我为空日期输出空白。如果它是空/null,那么逻辑会建议 ASP.NET 应该什么都不打印。

我还想如何输出空日期?我尝试添加 if 语句以防止尝试强制转换 null DateTimes,但这没有帮助,没有任何意义。

【问题讨论】:

    标签: c# asp.net sql-server sql-server-2008


    【解决方案1】:

    正如你所说,u.LastLogon 的数据类型是DateTime?。这意味着它可能有也可能没有价值。通过转换为DateTime,您需要它具有值。在这种情况下,它不会。

    根据您要使用它执行的操作,您可能需要检查 HasValue 属性:

    userRow["LastLogon"] = u.LastLogin.HasValue ? 
                           (object) u.LastLogin.ToShortDateString() : DBNull.Value;
    

    如果您的数据库 LastLogon 列是 DateTime 类型,那么您应该可以这样做:

    userRow["LastLogon"] = u.LastLogin.HasValue ? 
                           (object) u.LastLogin.Value : DBNull.Value;
    

    【讨论】:

    • 那我该怎么办呢?我不投吗?我是否继续在 DateTime 上使用 ShortDateString()?而不是 DateTime ?
    • u.LastLogon.Value.ToShortDateString() 到底是怎么不起作用的?
    • 显然由于 DBNull.Value 行而无法正常工作。由于 userRow["LastLogon"] 被认为是字符串。用 String.Empty 替换它可以工作。很抱歉造成混乱。
    • userRow["LastLogon"] = u.LastLogon.HasValue ? u.LastLogon.Value.ToShortDateString() : String.Empty
    • 已编辑:您需要先转换为object。您应该确认这在数据库中有效。 String.Empty 在数据库方面与 NULL 不同。列的类型是什么?
    【解决方案2】:

    问题是 .NET null 与 SQL NULL 不一样。 SQL Null 是 System.DBNull。所以它是 .NET 中的 [非null] 值。

    【讨论】:

    • 那么我该如何做才能让它不打印任何内容或打印日期(如果有)?
    • 技术上 Frazell 是正确的,但我很确定翻译是自动发生的。如果您的日期时间列为空,您将看到一个 .net 空值。但这不是问题,您必须编写一些代码来检查它是否为空并且什么也不打印。如您所见,最紧凑的方法是使用 ?。 ASP.NET 不会为您执行此操作。
    【解决方案3】:

    您需要在数据访问代码中执行以下操作:

    DataTable  dt       = ExecuteSomeQuery() ;
    object     value    = dt.Rows[0]["nullable_datetime_column"] ;
    DateTime?  instance = value != null && value is DateTime ? (DateTime?)value : (DateTime?)null ) ;
    

    如果返回的列是 NULL,它将作为 System.DBNull 返回,否则将作为 DateTime 的实例返回(或任何适当的映射类型 — int、string 等)。因此,您需要在尝试强制转换之前检查查询返回的对象类型。

    【讨论】:

    • 日期时间已经到了?类型。现在我想使用 DateTime 类中的 ShortDateTimeString 函数将其转换为字符串。它不会让我。
    • 在这种情况下,string s = instance.HasValue ? instance.Value.ToString() : "" ; 应该可以解决问题。
    • 是的,没错。但是其他人以正确的格式击败了你。
    【解决方案4】:

    看起来您正试图在 DateTime 上调用方法 (dcdt.ToShortDateString())?它没有值(它确实是空的)。试试这个:

    dcdt.HasValue ? dcdt.ToShortDateString() : String.Empty;
    

    编辑(只需重新阅读问题):另外,不要尝试转换为 DateTime。保留可为空的。

    编辑#2(基于 cmets):

    试试这个:

    if (dcdt.HasValue) 
    { userRow["DateCreated"] = dcdt.ToShortDateString(); } 
    else
    { userRow = DbNull.Value }
    

    【讨论】:

    • u.LastLogon.HasValue ? u.LastLogon.Value.ToShortDateString() : DBNull.Value;或 u.LastLogon.HasValue ? u.LastLogon.ToShortDateString() : DBNull.Value;拒绝工作。它不会那样编译。 LastLogon 是 DateTime 的一种类型?
    • 那是因为 DBNull.Value 不是字符串 - 表达式必须返回一致的数据类型。我会适当地编辑
    • 我想我解决了。我用这个: userRow["LastLogon"] = u.LastLogon.HasValue ? u.LastLogon.Value.ToShortDateString() : String.Empty;
    【解决方案5】:

    我看到德克斯特问他应该怎么做。好吧,我会创建一个扩展。

    static class DateTimeExtensions
    {
        public static string ToString(this DateTime? dateTime, string format)
        {
            return dateTime.HasValue ? dateTime.Value.ToString(format) : String.Empty;
        }
    }
    

    然后你可以这样做:

    DateTime? dt = null;
    DateTime? dt2 = DateTime.Now;
    Console.WriteLine(dt.ToString("dd-MM-yy"));
    Console.WriteLine(dt2.ToString("dd-MM-yy"));
    

    请注意,如果对象为空,我可以在可空类型上调用扩展方法。

    【讨论】:

    • 这是一个不错的解决方案
    【解决方案6】:

    简答

    DateTime? dateTime = u.LastLogon?.ToShortDateString()
    

    【讨论】:

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