我正嘗試使用BulkCopy.WriteToServer()從Oracle向SQL Server執行1000萬行的批量插入操作。C#SqlBulkCopy錯誤恢復錯誤
我已經確定
- 表列和數據類型的兩側是相同的。我的意思是Oracle的Date數據類型映射到Sql Server的日期時間數據類型。 VARCHAR2映射到VARCHAR等
- 沒有觸發器和索引的目標表
當它來到剛剛約1.4萬行未能與System.ArgumentOutOfRangeException:時,分,秒參數描述了一個未 - 可表示日期時間。在System.DateTime.DateToTicks(的Int32年的Int32月的Int32日)
這裏是我的代碼
SqlBulkCopy copy;
copy = new SqlBulkCopy(destConn, SqlBulkCopyOptions.TableLock, null);
// ColumnMappings property is used to map column positions, not data type
copy.DestinationTableName = DestTable;
copy.NotifyAfter = 5000;
copy.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);
copy.BulkCopyTimeout = 0;
try { copy.WriteToServer((IDataReader)rd); }
catch (Exception ex)
{
AppInfo.TableMsg[SrcTable] = AppInfo.TableMsg[SrcTable] + "\r\n" + "bulkcopy.WriteToServer(rd) failed. " + ex.Message;
throw ex;
}
我的表有超過100列,有26個DATE列。很難理清其中的壞數據
所以我有3個問題在這裏
- 是否有設置/選項,以使在WriteToServer()繼續或忽略異常?或者我可以在catch block中做任何事情讓它繼續下去?我不在乎留下不良數據。我正在尋找一種方法來告訴它繼續出現插入錯誤。
- 有什麼辦法可以防止這種情況發生?例如,我可以在填充OracleDataReader的選擇查詢中做什麼?
- 如果上述兩個問題沒有解決方案,那麼有沒有什麼好方法可以清除Oracle端的「壞日期」?
感謝,
更新: 我做了以下
- 更改目標表中的數據類型從日期時間到DATETIME2
修改選擇列表
CASE WHEN my_date_column < To_Date('01/01/1753','mm/dd/yyyy')THEN To_Date('01/01/1753','mm/dd/yyyy ')ELSE my_date_column END
對於具有DATE數據類型的所有列。
但是錯誤仍然存在。這裏是完整的錯誤信息。
System.ArgumentOutOfRangeException was caught
HResult=-2146233086
Message=Hour, Minute, and Second parameters describe an un-representable DateTime.
Source=mscorlib
StackTrace:
at System.DateTime.TimeToTicks(Int32 hour, Int32 minute, Int32 second)
at Oracle.DataAccess.Client.OracleDataReader.GetDateTime(Int32 i)
at Oracle.DataAccess.Client.OracleDataReader.GetValue(Int32 i)
at System.Data.SqlClient.SqlBulkCopy.GetValueFromSourceRow(Int32 destRowIndex, Boolean& isSqlType, Boolean& isDataFeed, Boolean& isNull)
at System.Data.SqlClient.SqlBulkCopy.ReadWriteColumnValueAsync(Int32 col)
at System.Data.SqlClient.SqlBulkCopy.CopyColumnsAsync(Int32 col, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.CopyRowsAsync(Int32 rowsSoFar, Int32 totalRows, CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinued(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsync(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestContinuedAsync(BulkCopySimpleResultSet internalResults, CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalAsync(CancellationToken ctoken)
at System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServerAsync(Int32 columnCount, CancellationToken ctoken)
at System.Data.SqlClient.SqlBulkCopy.WriteToServer(IDataReader reader)
從錯誤消息看來,它看起來有問題的部分是OracleDataReader而不是SqlBulkCopy。
如何使用Oracle查詢快速發現這些違規值? 還有什麼建議嗎?
我更新了我的進一步信息的問題。需要進一步幫助。 – Shawn
「OracleDataReader.GetDateTime」中出現錯誤的事實表明SQL Server與它無關。閱讀時發生錯誤。 .NET DateTime(它與datetime2具有完全相同的範圍)無法表示某個日期值。在Oracle查詢工具中執行查詢並檢查結果。一定有一些錯誤。您可以按以下方式平分錯誤行:將查詢更改爲僅返回第1M行。如果錯誤再次發生,則它位於第一個1M行。如果不是,他們很清楚。排除它們並再次平分。找到有故障的行。 – usr
我明白了。感謝您的幫助。我很感激。 – Shawn