【问题标题】:Cannot cast DBNull.Value to type System.DateTime无法将 DBNull.Value 转换为 System.DateTime 类型
【发布时间】:2015-06-22 03:14:19
【问题描述】:

我不得不从不同的数据库中提取两个独立的数据查询,现在我试图将其合并到 C# 中的一个数据表中。但是,每当我有来自主要包含日期时间值的列的空值时,我都会收到错误消息。我似乎无法找出我能做些什么来解决它。我尝试过 if 语句来捕获空值等,但不断收到异常。

我收到以下错误:

System.InvalidCastException was unhandled
HResult=-2147467262
  Message=Cannot cast DBNull.Value to type 'System.DateTime'. Please use a nullable type.
  Source=System.Data.DataSetExtensions
  StackTrace:
       at System.Data.DataRowExtensions.UnboxT`1.ValueField(Object value)
       at System.Data.DataRowExtensions.Field[T](DataRow row, String columnName)
       at HueniData.Program.Main(String[] args) in c:\Visual Studio Projects\HueniData\HueniData\Program.cs:line 60
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

以下代码:

var resultTable = from t1 in actualTable.AsEnumerable()
                  join t2 in recipeTable.AsEnumerable()
                    on t1.Field<int>("Step No") equals t2.Field<int>("Step No")
                  select new { t1, t2 };


DataTable newTable = new DataTable();
newTable.Columns.Add("StepNo", typeof(int));
newTable.Columns.Add("ActualDuration", typeof(decimal));
newTable.Columns.Add("RecipeDuration", typeof(decimal));
newTable.Columns.Add("StartTime", typeof(DateTime));


DataRow newRow;
foreach (var dr in resultTable)
{
    newRow = newTable.NewRow();
    newRow["StepNo"] = dr.t1.Field<int>("Step No");
    newRow["ActualDuration"] = dr.t1.Field<decimal>("ActualDuration");
    newRow["RecipeDuration"] = dr.t2.Field<decimal>("RecipeDuration");
    **newRow["StartTime"] = dr.t1.Field<DateTime>("Step Start Time");**                                           
    newTable.Rows.Add(newRow);
}

更新: 下面的答案很有帮助,但我基本上都尝试过最初使用各种 if 语句并将 datetime 更改为 datetime?。我仍然得到错误。我解决这个问题的方法是使用:

 newTable.Columns.Add("StartTime", typeof(Object));
newRow["StartTime"] = dr.t1.Field<Object>("Step Start Time");

但如果有人能向我解释问题出在哪里,我仍然很想知道。

【问题讨论】:

  • 请不要假设。我进行了搜索,每次更改代码的尝试都会导致新的异常。您的评论没有帮助。

标签: c# datetime datatable nullable


【解决方案1】:

复制数据时不需要使用 Field() 方法。您可以直接复制该值而无需任何转换:

newTable.Columns.Add("StartTime", typeof(DateTime));

....

newRow["StartTime"] = dr.t1["Step Start Time"];

注意:DataColumn 类有一个 AllowDBNull 属性,它不适合与 Nullable 类型一起使用。在创建新列时,您可能需要考虑是否需要设置 AllowDBNull 以及与您的数据相关的任何其他属性。

我们对您的代码感到满意的是 Field() 旨在将可为空的 DateTime 列映射到 C# 等效的 DateTime?。 DataRow 对象将弱类型的值存储为普通对象,可以是 DateTime 值或 DBNull 值。

要使 Field() 工作,您必须执行以下操作:

// Note column type is DateTime not DateTime?
newTable.Columns.Add("StartTime", typeof(DateTime));

....

if (dr.t1.Field<DateTime?>("Step Start Time") != null) {
    newRow["StartTime"] = dr.t1.Field<DateTime>("Step Start Time");
} else {
    // This is not necessary if the DataColumn's default value is DBNull
    newRow["StartTime"] = DBNull.Value;
}

【讨论】:

    【解决方案2】:

    将您的DateTime 列设为nullable。您正在尝试将 null 值转换为 DateTime ,这将引发异常。更改以下代码

    newTable.Columns.Add("StartTime", typeof(DateTime?));
    

    当在DataTable 中添加行时,更改以下行

    newRow["StartTime"] = dr.t1.Field<DateTime?>("Step Start Time");
    

    【讨论】:

    • 即:错误来自dr.t1.Field&lt;DateTime&gt; 将其更改为dr.t1.Field&lt;DateTime?&gt; 将允许原始数据中的NULL(如null),然后要求发布者采取正确的纠正措施- 这可能会或可能不会传播 NULL 值。
    • 是的,这不起作用,我确实尝试过,认为这是解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    相关资源
    最近更新 更多