【发布时间】:2012-02-25 00:34:45
【问题描述】:
我编写了一个小型控制台应用程序,它指向一个包含 DBF/FoxPo 文件的文件夹。
然后它根据每个 dbf 表在 SQL 中创建一个表,然后进行批量复制以将数据插入到 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 溢出。必须在 1753 年 1 月 1 日凌晨 12:00:00 到 9999 年 12 月 31 日晚上 11:59:59 之间。
我在 google 上找到了一个结果,表明了问题所在:[A]... 和一个可能的解决方法 [B] (但我想将我的十进制值保留为十进制,并将日期保留为日期,如我会根据数据做进一步的计算)
我想做的解决方案
1.) 要么增加连接时间,(但我认为我不能增加它比我有的更多),或者是否可以拆分 OleDbDataReader 的结果并在增量批量插入中进行?
2.)我在想是否可以进行批量复制以忽略有错误的结果,或者将出错的记录记录到 csv 文件或类似程度?
【问题讨论】:
-
就回答 (1) 而言 - 这本来是我的建议。比如说 1000 次记录爆发。这应该解决这个问题,并希望防止冻结/锁定问题。至于 (2) - 如果缺少默认值,为什么不使用默认值 - 比如说 .MinValue 样式,或者可能 -1 表示十进制,01/01/1980 表示日期。 (这些只是示例 - 可以使用适合您需要的任何值)。
-
对如何进行增量阅读有任何想法吗?我一直在寻找,但到目前为止还没有运气......
标签: c# bulkinsert smo foxpro sqlbulkcopy