Я написал небольшое консольное приложение, указывающее на папку, содержащую файлы DBF/FoxPo.
Затем он создает таблицу в SQL на основе каждой таблицы dbf, а затем выполняет массовое копирование для вставки данных в SQL. По большей части это работает довольно хорошо, за исключением нескольких загвоздок.
1) Некоторые таблицы FoxPro содержат более 5000000 записей, и срок действия соединения истекает до завершения вставки.
Вот моя строка подключения:
<add name="SQL" connectionString="data source=source_source;persist security info=True;user id=DBFToSQL;password=DBFToSQL;Connection Timeout=20000;Max Pool Size=200" providerName="System.Data.SqlClient" />
Сообщение об ошибке: "Время ожидания истекло. Время ожидания истекло до завершения операции или сервер не отвечает."
КОД:
using (SqlConnection SQLConn = new SqlConnection(SQLString))
using (OleDbConnection FPConn = new OleDbConnection(FoxString))
{
ServerConnection srvConn = new Microsoft.SqlServer.Management.Common.ServerConnection(SQLConn);
try
{
FPConn.Open();
string dataString = String.Format("Select * from {0}", tableName);
using (OleDbCommand Command = new OleDbCommand(dataString, FPConn))
using (OleDbDataReader Reader = Command.ExecuteReader(CommandBehavior.SequentialAccess))
{
tbl = new Table(database, tableName, "schema");
for (int i = 0; i < Reader.FieldCount; i++)
{
col = new Column(tbl, Reader.GetName(i), ConvertTypeToDataType(Reader.GetFieldType(i)));
col.Nullable = true;
tbl.Columns.Add(col);
}
tbl.Create();
BulkCopy(Reader, tableName);
}
}
catch (Exception ex)
{
// LogText(ex, @"C:\LoadTable_Errors.txt", tableName);
throw ex;
}
finally
{
SQLConn.Close();
srvConn.Disconnect();
}
}
private DataType ConvertTypeToDataType(Type type)
{
switch (type.ToString())
{
case "System.Decimal":
return DataType.Decimal(18, 38);
case "System.String":
return DataType.NVarCharMax;
case "System.Int32":
return DataType.Int;
case "System.DateTime":
return DataType.DateTime;
case "System.Boolean":
return DataType.Bit;
default:
throw new NotImplementedException("ConvertTypeToDataType Not implemented for type : " + type.ToString());
}
}
private void BulkCopy(OleDbDataReader reader, string tableName)
{
using (SqlConnection SQLConn = new SqlConnection(SQLString))
{
SQLConn.Open();
SqlBulkCopy bulkCopy = new SqlBulkCopy(SQLConn);
bulkCopy.DestinationTableName = "schema." + tableName;
try
{
bulkCopy.WriteToServer(reader);
}
catch (Exception ex)
{
//LogText(ex, @"C:\BulkCopy_Errors.txt", tableName);
}
finally
{
SQLConn.Close();
reader.Close();
}
}
}
Мои вторая и третья ошибки следующие:
Я понимаю, в чем проблемы, но как их исправить, я не уверен
2) "Поставщик не смог определить значение Decimal. Например, строка была только что создана, значение по умолчанию для столбца Decimal недоступно, а потребитель еще не установил новое значение Decimal."
3) Переполнение SqlDateTime. Должно быть между 01.01.1753, 00:00:00 и 31.12.9999, 23:59:59.
Я нашел в Google результат, в котором указывалось, в чем проблема: "nofollow noreferrer">[A]... и возможный обходной путь [B] (но я бы хотел, чтобы мои десятичные значения были десятичными, а даты - датой, так как я буду выполнять дальнейшие вычисления с данными)
Что я хочу сделать в качестве решения
1.) Либо увеличьте время соединения (но я не думаю, что смогу увеличить его больше, чем у меня есть), или, в качестве альтернативы, возможно ли разделить результаты OleDbDataReader и выполнить инкрементную массовую вставку?
2.) Я подумал, возможно ли массовое копирование, чтобы игнорировать результаты с ошибками, или записать записи, которые выводят ошибки, в файл csv или что-то в этом роде?