从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的主要内容,如果未能解决你的问题,请参考以下文章