2011-01-20 68 views
2

我使用SQL Bulkcopy在asp.net 3.5與C#SQL Bulkcopy YYYYMMDD問題

一個字符串到日期的轉換問題,我讀了大量的CSV文件(CSV reader)。讀取的一個字符串應該加載到SQL Server 2008日期列中。

如果文本文件包含例如字符串'2010-12-31',則SQL Bulkcopy將其毫無問題地加載到Date列中。

然而,如果字符串是「201」,我得到一個錯誤:
從數據源String類型的給定值不能被轉換爲類型指定的目標列

該文件的日期包含8000萬條記錄,所以我不能創建一個數據表....

SqlBulkcopy Columnmappings等都可以。另外更改爲DateTime不起作用。

我試圖

SET DATEFORMAT ymd; 

但是,這並不能幫助。

任何想法如何告訴SQL Server接受這種格式?否則,我會在CSV閱讀器中創建一個自定義修復程序,但我更喜歡SQL中的某些內容。

更新 在兩個答案的後續行動,我使用SQL bulkcopy像這樣(在另一個問題#2建議):

的CSV讀者(見在CodeProject上面的鏈接)返回的字符串值(不是很強類型)。該CSVreader實現System.Data.IDataReader,所以我可以做這樣的事情:

using (CsvReader reader = new CsvReader(path)) 
using (SqlBulkCopy bcp = new SqlBulkCopy(CONNECTION_STRING)) 
{ bcp.DestinationTableName = "SomeTable"; 
    // columnmappings 
    bcp.WriteToServer(reader); } 

所有來自IDataReader的到來字段是字符串,所以除非我改變了不少在CSVreader

我不能使用C#方法

因此,我的問題與如何在C#中修復它無關,我可以這樣做,但我想阻止它。

很奇怪,因爲如果你在SQL東西搞得像

update set [somedatefield] = '201' 

它也可以,只是不能與bulkcopy。

任何想法爲什麼?

感謝您的任何建議, Pleun

回答

2

如果你能在C#本身韓德爾它那麼這個代碼將有助於獲得字符串作爲一個DateTime對象中,如果你希望它被格式化爲字符串,那麼你可以通過直接

//datestring is the string read from CSV 
DateTime thedate = DateTime.ParseExact(dateString, "yyyyMMdd", null); 

日期:

string thedate = DateTime.ParseExact(dateString, "yyyyMMdd", null).ToString("yyyy-MM-dd"); 

祝你好運。

更新

在您的情況我不知道爲什麼日期不自動格式化,但是從C#你需要得到的,並且在數據傳遞到WriteToServer()方法的過程產生干擾。我認爲你可以做的最好的事情(記住性能)是有一個DataRow項目的緩存,並將它們傳遞給WriteToServer()方法。我只寫代碼示例在一分鐘...

//A sample code.. polish it before implementation 
//A counter to track num of records read 
long records_read = 0; 
While(reader.Read()) 
{ 
    //We will take rows in a Buffer of 50 records 
    int i = records_read;//initialize it with the num of records last read 
    DataRow[] buffered_rows = new DataRow[50]; 
    for(;i<50 ;i++) 
    { 
     //Code to initialize each rows with the data in the reader 
     //..... 
     //Fill the column data with Date properly formatted 
     records_read++; 
     reader.Read(); 
    } 
    bcp.WriteToServer(buffered_rows); 
} 

它不是完整的代碼,但我認爲你可以解決它......

0

這不是完全清楚你是如何使用SqlBulkCopy,但最好你不應該在所有上傳字符串格式的數據到SQL Server:它解析爲DateTimeDateTimeOffset存儲在您的CSV閱讀器(或CSV閱讀器的輸出)中,然後以此方式上傳。那麼你不需要擔心字符串格式。

+0

我已經更新了關於如何使用SqlBulkCopy的簡短說明。我知道這並不理想,但是CSV閱讀器只返回字符串(如果SQL Server能夠直接接受這些字符串,它將會有8000萬行)。這很奇怪,因爲如果你做了一個sql更新集[somedatefield] ='201',它也可以工作,而不是使用批量拷貝。 – Pleun 2011-01-20 22:31:26

+2

@Pleun:我敢說你有辦法破壞它 - 但是如果我是你,我會咬緊牙關,自己進行轉換。將每個值設置爲適當類型只是一個更好的解決方案 - 這意味着您可以在客戶端儘早執行驗證。 – 2011-01-20 22:45:38

+1

感謝你們兩位 - 我會按照你的建議進行並咬緊牙關。 – Pleun 2011-01-21 09:26:56

1

舊的問題,而是想補充的替代方法。

我有與SQLBulkLoader相同的問題,當從IDataReader流時,不允許DataType/culture規格的列。

爲了減少在本地構建數據行的速度開銷,而不是在目標上進行解析,我使用的一個簡單方法是將線程文化暫時設置爲定義所用格式的文化 - 在這種情況下美國格式日期。

我的問題 - 的en-US日期輸入(PowerShell中):

[System.Threading.Thread]::CurrentThread.CurrentCulture = 'en-US' 
<call SQLBulkCopy> 

對於你的問題,你可以做相同的,但由於日期格式不特定文化,創建一個默認文化對象(未經測試):

CultureInfo newCulture = (CultureInfo) System.Threading.Thread.CurrentThread.CurrentCulture.Clone(); 
newCulture.DateTimeFormat.ShortDatePattern = "yyyyMMDD; 
Thread.CurrentThread.CurrentCulture = newCulture; 

我發現允許數據庫服務器進行類型轉換,一旦他們通過SqlBulkCopy的界面變得比執行本地解析,特別是在腳本語言相當快。