У меня проблема с преобразованием String to Date с использованием SQL Bulkcopy в asp.net 3.5 с C #
Я прочитал большой CSV-файл (с CSV-ридером ). Одна из прочитанных строк должна быть загружена в столбец даты SQL Server 2008.
Если текстовый файл содержит, например, строку '2010-12-31', SQL Bulkcopy загружает ее без каких-либо проблем в столбец Date.
Однако, если строка «20101231», я получаю сообщение об ошибке:
Данное значение типа String из источника данных не может быть преобразовано в дату типа указанного целевого столбца
Файл содержит 80 миллионов записей, поэтому я не могу создать datatable ....
SqlBulkcopy Columnmappings и т. Д. Все в порядке. Также изменение на DateTime не помогает.
Я пытался
SET DATEFORMAT ymd;
Но это не помогает.
Любые идеи, как сказать SQL Server принять этот формат? В противном случае я создам собственное исправление в CSV-ридере, но я бы предпочел что-то в SQL.
update После двух ответов я использую SQL-массивную копию (как предложено в Stackoverflow в другом вопросе):
Считыватель 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, являются строками, поэтому я не могу использовать подход c #, если я не изменю совсем немного в CSVreader
Поэтому мой вопрос не связан с тем, как исправить его на C #, я могу это сделать, но я хочу это предотвратить.
Это странно, потому что если вы делаете в sql что-то вроде
update set [somedatefield] = '20101231'
он также работает, просто не с помощью объемной копии.
Любая идея почему?
Спасибо за любой совет, Pleun
Если вы можете перенести его на сам 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 #, с которой вам нужно войти, и Interfere в процессе передачи данных WriteToServer()
. Лучше всего я думаю, что вы можете сделать (имея в виду Performance), чтобы иметь кеш элементов 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);
}
Его не полный код, но я думаю, вы можете это решить ...
Старая проблема, но хотелось добавить альтернативный подход.
У меня была такая же проблема с SQLBulkLoader, которая не позволяла спецификациям DataType / culture для столбцов при потоковой передаче из IDataReader.
Чтобы уменьшить скорость накладных расходов при построении datarows локально, и вместо этого синтаксический анализ происходит на цели, простой метод, который я использовал, заключался в том, чтобы временно установить культуру потока в культуру, которая определяет используемый формат - в этом случае для дат формата США ,
Для моей проблемы - даты в США на вкладке (в 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, значительно быстрее, чем выполнять парсинг локально, особенно на языке сценариев.