无法将DBNull.Value强制转换为System.DateTime

时间:2015-06-22 03:14:19

标签: c# datetime datatable nullable

我不得不从单独的数据库中提取两个单独的数据查询,现在我尝试将其合并到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语句和更改日期时间到日期时间?我仍然得到错误。我解决这个问题的方法是使用:

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

但如果有人能向我解释问题是什么,我仍然会喜欢。

2 个答案:

答案 0 :(得分:1)

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

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

....

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

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

我们讨厌您的代码是Field&lt;&gt;()用于将可空的DateTime列映射到C#等效的DateTime?。 DataRow对象将弱类型的值存储为普通对象,DateTime值或DBNull值。

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

// 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;
}

答案 1 :(得分:0)

制作DateTimenullable。您正在尝试将null值转换为DateTime,这将导致异常。更改以下代码

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

DataTable中添加行时更改以下行

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