I have a String to Date conversion problem using SQL Bulkcopy in asp.net 3.5 with C#
I read a large CSV file (with CSV reader). One of the strings read should be loaded into a SQL server 2008 Date column.
If the textfile contains for example the string '2010-12-31', SQL Bulkcopy开发者_StackOverflow社区 loads it without any problems into the Date column.
However, if the string is '20101231', I get an error:
The given value of type String from the data source cannot be converted to type date of the specified target columnThe file contains 80 million records so I cannot create a datatable....
SqlBulkcopy Columnmappings etc. are all ok. Also changing to DateTime does not help.
I tried
SET DATEFORMAT ymd;
But that does not help.
Any ideas how to tell SQL Server to accept this format? Otherwise I will create a custom fix in CSV reader but I would prefer something in SQL.
update Following up on the two answers, I am using SQL bulkcopy like this (as proposed on Stackoverflow in another question):
The CSV reader (see the link above on codeproject) returns string values (not strong typed). The CSVreader implements System.Data.IDataReader so I can do something like this:
using (CsvReader reader = new CsvReader(path))
using (SqlBulkCopy bcp = new SqlBulkCopy(CONNECTION_STRING))
{ bcp.DestinationTableName = "SomeTable";
// columnmappings
bcp.WriteToServer(reader); }
All the fields coming from the iDataReader are strings, so I cannot use the c# approach unless I change quite a bit in the CSVreader
My question is therefore not related on how to fix it in C#, I can do that but i want to prevent that.
It is strange, because if you do a in sql something like
update set [somedatefield] = '20101231'
it also works, just not with bulkcopy.
Any idea why?
Thanks for any advice, Pleun
Older issue, but wanted to add an alternative approach.
I had the same issue with SQLBulkLoader not allowing DataType/culture specifications for columns when streaming from IDataReader.
In order to reduce the speed overhead of constructing datarows locally and instead have the parsing occur on the target, a simple method I used was to temporarily set the thread culture to the culture which defines the format in use - in this case for US format dates.
For my problem - en-US dates in the input (in Powershell):
[System.Threading.Thread]::CurrentThread.CurrentCulture = 'en-US'
<call SQLBulkCopy>
For your problem, you could do the same but since the date format is not culture specific, create a default culture object (untested):
CultureInfo newCulture = (CultureInfo) System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
newCulture.DateTimeFormat.ShortDatePattern = "yyyyMMDD;
Thread.CurrentThread.CurrentCulture = newCulture;
I found allowing the database server to perform the type conversions once they've gotten through the SQLBulkCopy interface to be considerably faster than performing parsing locally, particularly in a scripting language.
If you can handel it in C# itself then this code will help get the date in the string as a DateTime object which you can pass directly
//datestring is the string read from CSV
DateTime thedate = DateTime.ParseExact(dateString, "yyyyMMdd", null);
If you want it to be formatted as string then:
string thedate = DateTime.ParseExact(dateString, "yyyyMMdd", null).ToString("yyyy-MM-dd");
Good luck.
Update
In your scenario i don't know why date is not automatically formatted but from C# you need to get in and Interfere in the process of passing the data to the WriteToServer() method. Best i think you can do (keeping in mind the Performance) is to have a cache of DataRow items and Pass them to the WriteToServer() method. I will just write the sample code in a minute...
//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);
}
Its not full code but i think you can work it out...
It's not entirely clear how you're using SqlBulkCopy, but ideally you shouldn't be uploading the data to SQL Server in string format at all: parse it to a DateTime or DateTimeOffset in your CSV reader (or on the output of your CSV reader), and upload it that way. Then you don't need to worry about string formats.
加载中,请稍侯......
精彩评论