从C#中的数据中删除特殊字符后如何将dbf文件中的数百万行数据上传到SQL Server

Posted

技术标签:

【中文标题】从C#中的数据中删除特殊字符后如何将dbf文件中的数百万行数据上传到SQL Server【英文标题】:How to upload millions of rows of data from dbf file to SQL Server after removing special characters from the data in C# 【发布时间】:2021-01-18 15:38:05 【问题描述】:

我的任务是在删除记录中存在的特殊字符后将.dbf 文件上传到 SQL Server。

我使用了正则表达式来删除特殊字符。首先将数据加载到数据读取器中,然后再加载到数据表中。

在再次对数据进行一些操作后,数据被加载到数据表中,然后使用批量复制插入数据被加载到数据库中。

150000 行运行良好,但对于 300 万行,当数据加载到数据表中时,我得到一个 OutOfMemoryException

    DataTable dt = new DataTable();

    using (OleDbDataReader dr = cmd.ExecuteReader())
    
        //Logic to Remove Special Characters from the file.
        dt.Load(dr); //OutOfMemoryException occurred here

        foreach (DataRow row in dt.Rows)
        
            for (int i = 0; i < dt.Columns.Count; i++)
            
                if (dt.Columns[i].DataType == typeof(string))
                    row[i] = Regex.Replace(row[i].ToString(), "[#$%^*@!~?]", "");
            
        

        dt.AcceptChanges();

        // Bulk Copy to SQL Server
        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn))
        
             // code for bulk insert
             bulkCopy.WriteToServer(dt);
        
    

【问题讨论】:

我建议您为此使用 SSIS。它非常快速且易于使用 而网络用户上传文件将如何做到这一点?现在您可以使用 Shell() SSIS,但话又说回来,假设虚拟主机具有可用的 SSIS(这不是给定的)。而且我不相信 SSIS 有能力清除有趣的角色——是吗?所以你错过了这艘离开港口的船有两个原因。 【参考方案1】:

问题是,你一次读取所有行,这显然会导致OutOfMemoryException等问题。

您想要做的是,不要一次将所有数据从 OleDbDataReader 加载到 DataTable 对象。

这是我所看到的我提出的解决方案,您想批量插入行:

调用ExecuteReader()方法后,获取 表。 获取当前表架构并将列添加到您的DataTable 对象中。 (此DataTable 对象将用于将行批量发布到 SQL) 逐行阅读OleDbDataReader 并将这些行复制到您复制架构的DataTable(dr.Read() 方法会逐行读取数据). 检查行数何时超过 1000 或如果没有其他行,请使用 BulkCopy 将您手头的记录提交到 SQL,然后清除表。 (你可以根据你的记忆力增加这个数字) 重复直到没有其他行。

这是您按照我建议的方式重新编写的代码:

using (System.Data.OleDb.OleDbDataReader dr = cmd.ExecuteReader())

    var schemaTable = dr.GetSchemaTable(); // Get Metadata of the current table.
    var dt = new DataTable();
    foreach (DataRow row in schemaTable.Rows) // Copy the schema to your datatable object
    
        string colName = row.Field<string>("ColumnName");
        System.Type t = row.Field<System.Type>("DataType");
        dt.Columns.Add(colName, t);
    
    bool hasNextRow = false;
    do
    
        if (!hasNextRow) 
        
            // We have to do this in order to peek through the next row. If we do not have next row, then we will have to commit the current changes
            hasNextRow = dr.Read();
        
        if(!hasNextRow) break; // Break if there is no row.
        var newRow = dt.NewRow(); 
        foreach (DataColumn col in dt.Columns) // Copy current row
        
            newRow[col.ColumnName] = dr[col.ColumnName];
        
        dt.Rows.Add(newRow);
        dt.AcceptChanges();
        hasNextRow = dr.Read();
        if (dt.Rows.Count >= 1000 || !hasNextRow) // When the data exceeds thousands rows Or when there are no further rows, insert the data into sql and clear the memory. 
        
            foreach (DataRow row in dt.Rows) // Adjust the values
            
                 for (int i = 0; i < dt.Columns.Count; i++)
                 
                     if (dt.Columns[i].DataType == typeof(string))
                         row[i] = Regex.Replace(row[i].ToString(), "[#$%^*@!~?]", "");
                 
            
            dt.AcceptChanges();
            // Bulk Copy to SQL Server
            using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn))
            
                // code for bulk insert
                bulkCopy.WriteToServer(dt);
            

            dt.Rows.Clear(); // Clear the memory so new rows can be read.
            dt.AcceptChanges();
        
     while(hasNextRow);

PS:代码未经测试,因此可能需要一些关爱。

【讨论】:

以上是关于从C#中的数据中删除特殊字符后如何将dbf文件中的数百万行数据上传到SQL Server的主要内容,如果未能解决你的问题,请参考以下文章

C#删除字符串中的回车换行空格等特殊字符

无法删除 Pig 中的特殊字符

使用 spark 从 csv 文件中删除所有特殊字符

c#如何把字符串中的指定字符删除

使用特殊字符定义字段名称,例如python dbf中的^

.net中如何将网页中的数据导出成dbf(access)文件