Я решил заменить/преобразовать DataTable в IDataReader из-за проблем с памятью.Как создать собственный класс w/IDataReader из LumenWorks (Fast CSV Reader) для использования SqlBulkCopy, имея несколько разных версий файлов?
После долгого времени Google & Поиск в MSDN, я натолкнулся на это в http://www.michaelbowersox.com/2011/12/22/using-a-custom-idatareader-to-stream-data-into-a-database/ и Bulk Insert Sql Server millions of record.
Поскольку я использую LumenWorks Fast CSV Reader, и я еще не понял, как сообщить CsvReader, что IDataReader использует две разные версии полей. :-(CsvReader.FieldCount является ключевым здесь, но я не вижу, как сказать CsvReader использовать один из двух новых классов, имеющих интерфейс IDataReader. См. Исходный скрипт и измененный скрипт ниже ... Спасибо ...
// Оригинальные сценарии ...
var dbConnection = new SqlConnection(_dbConnectionString);
using (var dbBulkCopy = new SqlBulkCopy(dbConnection)
{
using (CsvReader csvReader = new CsvReader(new StreamReader(filePath), false, '|', '"', '\\', '#', ValueTrimmingOptions.UnquoteOnly))
{
while(csvReader.ReadNextRecord())
{
if (csvReader.FieldCount == 48)
{
//Version 1...
dataRow["DealerId"] = csvReader[0];
dataRow["DealerName"] = csvReader[1];
//Etc...
}
else if (csvReader.FieldCount == 51)
{
//Version 2...
dataRow["DealerId"] = csvReader[0];
dataRow["DealerName"] = csvReader[1];
//Etc...
}
else { throw new Exception("Field Total Count Mismatched"); }
dataTable.Rows.Add(dataRow);
}
dbConnection.Open();
dbBulkCopy.WriteToServer(dataTable);
}
}
// Новый скрипт ...
var dbConnection = new SqlConnection(_dbConnectionString);
using (var dbBulkCopy = new SqlBulkCopy(dbConnection)
{
dbConnection.Open();
using (CsvReader csvReader = new CsvReader(new StreamReader(filePath), false, '|', '"', '\\', '#', ValueTrimmingOptions.UnquoteOnly))
{
csvReader.ReadNextRecord();
dbBulkCopy.WriteToServer(
if (csvReader.FieldCount == 48)
{
//Version 1...
csvReader....??? //Assign a custom class having IDataTable...
}
else if (csvReader.FieldCount == 51)
{
//Version 2...
csvReader....??? //Assign a custom class having IDataTable...
}
else { throw new Exception("Field Total Count Mismatched"); }
);
}
}
// Пример сценария ...
using (var file = new StreamReader(path))
using (var csv = new CsvReader(file, true)) // true = has header row
using (var bcp = new SqlBulkCopy(connection)) {
bcp.DestinationTableName = "TableName";
bcp.WriteToServer(csv);
}
Я бы предложил посмотреть @ [это сообщение] (http://stackoverflow.com/questions/7791563/load-very-big-csv-files-into-s-sql-server-database). Чтение csv в таблицах данных, а затем вставка их может быть болезненной. И для вашего конкретного случая у меня когда-то была аналогичная проблема. Файл csv, который я получал, не был форматирован равномерно. Поэтому я добавил шаг 0 перед всеми другими видами лечения, и этот шаг состоял в том, чтобы удалить сильно отформатированные строки и/или переформатировать их должным образом [Вы можете даже разбить файл на создание 2: один для 48 полей, другой - по 51). Затем, используя sqlbulkcopy, вы можете легко переносить данные. –
Я добавил коды «Пример сценария» из предоставленной веб-ссылки. Я не уверен, что такое шаг 0, о котором вы говорите.Предположим, у меня есть 23 файла в папке, и каждый из них запускается по одному за раз. 13 файлов имеют 48 полей и 10 файлов имеют 51 поле по всем строкам. Таблица базы данных содержит 51 поле. У меня не возникло бы проблемы с файлом flat/50 полей, но 48 полей плоского файла, я не вижу, как сказать классу IDataReader использовать значения по умолчанию для 4 отсутствующих полей. – fletchsod
Я написал ответ, так как комментарии не будут предлагать достаточное место. –