Я импортирую некоторые данные из базы данных FoxPro в базу данных Sql Server, используя драйвер FoxPro OLE-DB. Подход, который я использую, состоит в том, чтобы пройтись по таблицам FoxPro, выбрать все записи в DataTable и затем использовать SqlBulkCopy для вставки этой таблицы в Sql Server. Это работает нормально, за исключением нескольких случаев, когда я получаю следующую ошибку:
System.InvalidOperationException: The provider could not determine the Decimal value. For example, the row was just created, the default for the Decimal column was not available, and the consumer had not yet set a new Decimal value.
Я исследовал это и зарегистрировал, с какими строками он появляется, и проблема в том, что таблица FoxPro имеет фиксированную ширину для числового значения. 1 сохраняется как 1,00, однако 10 хранится как 10,0, и это одна цифра после десятичной точки, которая вызывает проблемы. Теперь, найдя проблему, я изо всех сил пытаюсь ее исправить. Следующая функция - это то, что я использую для преобразования OLEDBReader в DataTable:
private DataTable FPReaderToDataTable(OleDbDataReader dr, string TableName)
{
DataTable dt = new DataTable();
//get datareader schema
DataTable SchemaTable = dr.GetSchemaTable();
List<DataColumn> cols = new List<DataColumn>();
if (SchemaTable != null)
{
foreach (DataRow drow in SchemaTable.Rows)
{
string columnName = drow["ColumnName"].ToString();
DataColumn col = new DataColumn(columnName, (Type)(drow["DataType"]));
col.Unique = (bool)drow["IsUnique"];
col.AllowDBNull = (bool)drow["AllowDBNull"];
col.AutoIncrement = (bool)drow["IsAutoIncrement"];
cols.Add(col);
dt.Columns.Add(col);
}
}
//populate data
int RowCount = 1;
while (dr.Read())
{
DataRow row = dt.NewRow();
for (int i = 0; i < cols.Count; i++)
{
try
{
row[((DataColumn)cols[i])] = dr[i];
}
catch (Exception ex) {
if (i > 0)
{
LogImportError(TableName, cols[i].ColumnName, RowCount, ex.ToString(), dr[0].ToString());
}
else
{
LogImportError(TableName, cols[i].ColumnName, RowCount, ex.ToString(), "");
}
}
}
RowCount++;
dt.Rows.Add(row);
}
return dt;
}
То, что я хотел бы сделать, это проверить значения, которые имеют проблему с 1 десятичным знаком, но я вообще не могу читать с устройства чтения данных в этих случаях. Я бы подумал, что мог бы использовать dr.GetString (i) в поврежденных строках, однако это затем возвращает следующую ошибку:
The provider could not determine the String value. For example, the row was just created, the default for the String column was not available, and the consumer had not yet set a new String value.
Я не могу обновить данные FoxPro, поскольку столбец не позволяет этого, как я могу прочитать запись из DataReader и исправить ее? Я перепробовал все комбинации casting / dr.GetValue / dr.GetData, и все они дают варианты одной и той же ошибки.
Структура таблицы FoxPro выглядит следующим образом:
Number of data records: 1664
Date of last update: 11/15/10
Code Page: 1252
Field Field Name Type Width Dec Index Collate Nulls Next Step
1 AV_KEY Numeric 6 Asc Machine No
2 AV_TEAM Numeric 6 No
3 AV_DATE Date 8 No
4 AV_CYCLE Numeric 2 No
5 AV_DAY Numeric 1 No
6 AV_START Character 8 No
7 AV_END Character 8 No
8 AV_SERVICE Numeric 6 No
9 AV_SYS Character 1 No
10 AV_LENGTH Numeric 4 2 No
11 AV_CWEEKS Numeric 2 No
12 AV_CSTART Date 8 No
** Total ** 61
Это столбец av_length, который вызывает проблему