C#批量复制、DBF错误(Timout和提供商无法确定…)

C#批量复制、DBF错误(Timout和提供商无法确定…),c#,bulkinsert,smo,foxpro,sqlbulkcopy,C#,Bulkinsert,Smo,Foxpro,Sqlbulkcopy,我已经编写了一个小型控制台应用程序,指向一个包含DBF/FoxPo文件的文件夹 然后,它基于每个dbf表在SQL中创建一个表,然后执行大容量复制以将数据插入SQL。除了一些障碍外,它在大多数情况下都运行得很好 1) 在插入完成之前,一些FoxPro表包含5000000+条记录和连接表达式 这是我的连接字符串: <add name="SQL" connectionString="data source=source_source;persist security info=True;user

我已经编写了一个小型控制台应用程序,指向一个包含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" />
。。。还有一个可能的解决办法(但我希望保留十进制值为十进制,日期为日期,因为我将对数据进行进一步计算)

我想做什么作为解决方案

1.)要么增加连接时间(但我认为我不能再增加连接时间),要么可以拆分OleDbDataReader的结果并进行增量批量插入

2.)我在想,是否有可能让大容量复制忽略有错误的结果,或者让出错的记录记录到csv文件或其他类似的文件中?

因此,在执行“for”语句时,我可能会将其分解,一次执行这么多:

int i = 0;
int MaxCount = 1000;

while (i < Reader.FieldCount)
{
    var tbl = new Table(database, tableName, "schema"); 

    for (int j = i; j < MaxCount; j++) 
    {                            
        col = new Column(tbl, Reader.GetName(j), ConvertTypeToDataType(Reader.GetFieldType(j))); 
        col.Nullable = true; 
        tbl.Columns.Add(col);
        i++;                      
    } 

    tbl.Create();                        
    BulkCopy(Reader, tableName); 
}
inti=0;
int MaxCount=1000;
而(i
因此,“i”跟踪总体计数,“j”跟踪增量计数(即一次计数的最大值),当您创建“批处理”时,您创建表并批量复制它

这看起来像你所期望的吗

干杯,

Chris。

这是我目前尝试的大容量复制方法,我无法处理大约90%的表,但我得到了一个OutOfMemory例外,较大的表。。。我希望将读取器的数据拆分为更小的部分,而不必先将其传递到数据表并存储在内存中(这是导致较大结果集上OutOfMemory异常的原因)

更新

我修改了下面的代码,以了解它在我的解决方案中的外观。。这并不漂亮。。但它是有效的。我将进行一些重构,并再次更新我的答案

    private void BulkCopy(OleDbDataReader reader, string tableName, Table table)
    {
        Console.WriteLine(tableName + " BulkCopy Started.");
        try
        {
            DataTable tbl = new DataTable();
            List<Type> typeList = new List<Type>();
            foreach (Column col in table.Columns)
            {
                tbl.Columns.Add(col.Name, ConvertDataTypeToType(col.DataType));
                typeList.Add(ConvertDataTypeToType(col.DataType));
            }

            int batch = 1;
            int counter = 0;

            DataRow tblRow = tbl.NewRow();

            while (reader.Read())
            {
                counter++;
                int colcounter = 0;
                foreach (Column col in table.Columns)
                {
                    try
                    {
                        tblRow[colcounter] = reader[colcounter];
                    }
                    catch (Exception)
                    {
                        tblRow[colcounter] = GetDefault(typeList[0]);
                    }
                    colcounter++;
                }

                tbl.LoadDataRow(tblRow.ItemArray, true);

                if (counter == BulkInsertIncrement)
                {
                    Console.WriteLine(tableName + " :: Batch >> " + batch);
                    counter = PerformInsert(tableName, tbl, batch);
                    batch++;
                }
            }

            if (counter > 0)
            {
                Console.WriteLine(tableName + " :: Batch >> " + batch);
                PerformInsert(tableName, tbl, counter);
            }

            tbl = null;
            Console.WriteLine("BulkCopy Success!");
        }
        catch (Exception ex)
        {
            Console.WriteLine("BulkCopy Fail!");
            SharedLogger.Write(ex, @"C:\BulkCopy_Errors.txt", tableName);
            Console.WriteLine(ex.Message);
        }
        finally
        {
            reader.Close();
            reader.Dispose();

        }
        Console.WriteLine(tableName + " BulkCopy Ended.");
        Console.WriteLine("*****");
        Console.WriteLine("");
    }
private void BulkCopy(OleDbDataReader读取器、字符串tableName、Table表)
{
Console.WriteLine(tableName+“BulkCopy已启动”);
尝试
{
DataTable tbl=新的DataTable();
列表类型列表=新列表();
foreach(表中的列col.Columns)
{
tbl.Columns.Add(col.Name,ConvertDataTypeToType(col.DataType));
typeList.Add(ConvertDataTypeToType(col.DataType));
}
int批=1;
int计数器=0;
DataRow tblRow=tbl.NewRow();
while(reader.Read())
{
计数器++;
int colcounter=0;
foreach(表中的列col.Columns)
{
尝试
{
tblRow[colcounter]=读卡器[colcounter];
}
捕获(例外)
{
tblRow[colcounter]=GetDefault(类型列表[0]);
}
colcounter++;
}
tbl.LoadDataRow(tblRow.ItemArray,true);
if(计数器==批量插入增量)
{
Console.WriteLine(tableName+“::Batch>>”+Batch);
计数器=PerformInsert(表名、tbl、批次);
批处理++;
}
}
如果(计数器>0)
{
Console.WriteLine(tableName+“::Batch>>”+Batch);
PerformInsert(表名、tbl、计数器);
}
tbl=null;
控制台.WriteLine(“批量复制成功!”);
}
捕获(例外情况除外)
{
控制台.WriteLine(“批量复制失败!”);
Write(例如,@“C:\BulkCopy_Errors.txt”,tableName);
控制台写入线(例如消息);
}
最后
{
reader.Close();
reader.Dispose();
}
Console.WriteLine(tableName+“BulkCopy已结束”);
Console.WriteLine(“*******”);
控制台。写线(“”);
}

在回答第(1)项的研究中——这是我的建议。以1000次记录的爆发来做。这将解决该问题,并有望防止冻结/锁定问题。至于(2)-如果缺少默认值,为什么不使用它们呢?比如说.MinValue样式,或者-1表示十进制,01/01/1980表示日期。(这些只是例子——任何适合您需要的值都可以使用)。您对如何进行增量读取有何想法?我一直在寻找,但还没有运气…我知道你要做什么,这是一种权利。。。尽管如此,您修改的代码部分负责创建列和表。我需要增量地将数据传递给sql,这将意味着对BulkCopy方法的修改。。我将发布我目前的尝试作为答案,我想做的是将创建表的代码重构为自己的方法。然后,您可以在我提到的for循环之前调用它,这样它只执行一次,然后您的批量复制只处理复制。从技术上讲,你有一种做两件事的方法——把关注点分开思考。一个方法执行一项作业。该表用于临时存储,因为我无法拆分OleDbDataReader。。但是谢谢你的投入。
    private void BulkCopy(OleDbDataReader reader, string tableName, Table table)
    {
        Console.WriteLine(tableName + " BulkCopy Started.");
        try
        {
            DataTable tbl = new DataTable();
            List<Type> typeList = new List<Type>();
            foreach (Column col in table.Columns)
            {
                tbl.Columns.Add(col.Name, ConvertDataTypeToType(col.DataType));
                typeList.Add(ConvertDataTypeToType(col.DataType));
            }

            int batch = 1;
            int counter = 0;

            DataRow tblRow = tbl.NewRow();

            while (reader.Read())
            {
                counter++;
                int colcounter = 0;
                foreach (Column col in table.Columns)
                {
                    try
                    {
                        tblRow[colcounter] = reader[colcounter];
                    }
                    catch (Exception)
                    {
                        tblRow[colcounter] = GetDefault(typeList[0]);
                    }
                    colcounter++;
                }

                tbl.LoadDataRow(tblRow.ItemArray, true);

                if (counter == BulkInsertIncrement)
                {
                    Console.WriteLine(tableName + " :: Batch >> " + batch);
                    counter = PerformInsert(tableName, tbl, batch);
                    batch++;
                }
            }

            if (counter > 0)
            {
                Console.WriteLine(tableName + " :: Batch >> " + batch);
                PerformInsert(tableName, tbl, counter);
            }

            tbl = null;
            Console.WriteLine("BulkCopy Success!");
        }
        catch (Exception ex)
        {
            Console.WriteLine("BulkCopy Fail!");
            SharedLogger.Write(ex, @"C:\BulkCopy_Errors.txt", tableName);
            Console.WriteLine(ex.Message);
        }
        finally
        {
            reader.Close();
            reader.Dispose();

        }
        Console.WriteLine(tableName + " BulkCopy Ended.");
        Console.WriteLine("*****");
        Console.WriteLine("");
    }