2015-06-22 225 views
0

我不得不從單獨的數據庫中提取兩個單獨的數據查詢,現在我試圖將它合併到C#中的一個數據表中。但是,每當我從主要包含日期時間值的列產生空值時,我都會收到錯誤。我似乎無法找到我可以做些什麼來解決它。我試過如果語句來捕獲空值等,但不斷收到異常。無法將DBNull.Value轉換爲輸入System.DateTime

我收到以下錯誤:

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

UPDATE: 下面的答案是有益的,但我已經基本試圖做這兩個原本使用各種if語句並將datetime更改爲datetime ?.我仍然得到錯誤。我解決這個問題的方法是使用:

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

但如果任何人都可以向我解釋了什麼問題我還是很想知道。

+0

請不要承擔。我做了搜索,每次嘗試更改代碼導致出現新的異常。您的評論沒有幫助。 – Danrex

回答

0

使您的DateTimenullable。您正試圖將null的值投射到DateTime,這將引發異常。更改下面的代碼

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

而且在DataTable變化添加行時以下行

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

即:錯誤來自'dr.t1。字段'將其更改爲'dr.t1.Field '將允許來自原始數據的NULL(作爲'null'),然後要求發佈者採取正確的糾正措施 - 這可能是也可能不是傳播NULL值。 – user2864740

+0

是的這不起作用我實際上嘗試這個想法是它的解決方案。 – Danrex

0

既然你知道DateTime領域有潛在的空值,現在你會從數據庫中獲取將DBNull類型,與null類型不同,因此您必須修改代碼,如下所示:

newRow["StartTime"] = !Convert.IsDBNull(dr.t1.Field<DateTime?>("Step Start Time")) ? dr.t1.Field<DateTime?>("Step Start Time") : DBNull.Value ; 

此代碼檢查內部數據是否爲DBNull,爲是,則一個.net Null值分配給對象或其他使用DataReader

+0

我會試試這個。我可以看到問題所在,我只是不知道如何解決問題。這似乎是正確的途徑。 – Danrex

+0

'System.DateTime'和''之間沒有隱式轉換' – Danrex

+0

我試圖通過更改上面的代碼來允許它使用空值,因此它是並且編譯時錯誤消失,但現在它聲明拋出例外情況:無法將列'StartTime'設置爲空。請改用DBNull。 – Danrex

1

保留原來的值取你並不需要使用現場<>()方法當複製數據時。您可以直接值只複製沒有任何鑄造:

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

.... 

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

注:DataColumn類具有AllowDBNull屬性,它不是設計與可空<>類型一起使用。在創建新列時,您可能需要考慮是否需要設置AllowDBNull和任何其他與數據相關的屬性。

我們對你的代碼進行的操作是字段<>()被設計爲將一個可爲空的DateTime列映射到與C#等價的DateTime ?. DataRow對象將弱類型的值存儲爲普通對象,即DateTime值或DBNull值。

進行實地<>()工作,你會做這樣的事情:

// 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; 
} 
相關問題