![](/img/trans.png)
[英]SqlBulkCopy and DataTables with Parent/Child Relation on Identity Column
[英]SqlBulkCopy DataTables as they are added to a DataSet
我想将 csv 中的值解析为数据表块,将它们添加到数据集,然后使用 SQLBulkCopy 将数据表插入到 SQL 中的单个表中。 原始 csv 的范围可以从 4 GB 到 8 GB,我需要避免将整个内容读入内存,因此分块。 我粗略地根据这篇文章进行了分块。 我使用LumenWorks来解析 csv 值。
将数据表添加到数据集后,我想使用 SqlBulkCopy 将其插入到我的 SQL 表中,同时创建下一个数据表。 SqlBulkCopy 完成后,我想删除数据表以释放内存。
我的第一个想法是在没有 await 的情况下异步运行分块方法,然后运行一个 while 循环来检查数据集中是否存在下一个数据表。 如果数据表存在,则批量复制。 如果数据表行数小于行限制,则它是最后一个块并停止 while 循环。
我会以错误的方式解决这个问题吗? 如果没有,我怎么能做这样的事情?
string filePath = @"C:\Users\user\Downloads\Testing\file - Copy.csv";
DataSet ds = new DataSet();
bool continueInsert = true;
int rowLimit = 100000;
int tableNumber = 0;
//Start this, but do not wait for it to complete before starting while loop
ChunkCSV(filePath, ds, rowLimit);
//Run SqlBulkCopy if datatable exists
while (continueInsert)
{
if (ds.Tables.Contains("tbl_" + tableNumber))
{
DataTable dataTable = ds.Tables["tbl_" + tableNumber];
//SqlBulkCopy dataTable code HERE
if (ds.Tables["tbl_" + tableNumber].Rows.Count < rowLimit)
{
continueInsert = false;
}
//Remove datatable from dataset to release memory
ds.Tables.Remove("tbl_" + tableNumber);
tableNumber++;
}
else
{
Thread.Sleep(1000);
}
}
这是我的分块代码:
private static void ChunkCSV(string filePath, DataSet dataSet, int rowLimit)
{
char delimiter = ',';
DataTable dtChunk = null;
int tableNumber = 0;
int chunkRowCount = 0;
bool firstLineOfChunk = true;
using (var sr = new StreamReader(filePath))
using (CsvReader csv = new CsvReader(sr, false, delimiter, '\"', '\0', '\0', ValueTrimmingOptions.All, 65536))
{
int fieldCount = csv.FieldCount;
string[] row = new string[fieldCount];
//Add fields when necessary
csv.MissingFieldAction = MissingFieldAction.ReplaceByEmpty;
while (csv.ReadNextRecord())
{
if (firstLineOfChunk)
{
firstLineOfChunk = false;
dtChunk = CreateDataTable(fieldCount, tableNumber);
}
DataRow dataRow = dtChunk.NewRow();
csv.CopyCurrentRecordTo(row);
for (int f = 0; f < fieldCount; f++)
{
dataRow[f] = row[f];
}
dtChunk.Rows.Add(dataRow);
chunkRowCount++;
if (chunkRowCount == rowLimit)
{
firstLineOfChunk = true;
chunkRowCount = 0;
tableNumber++;
dataSet.Tables.Add(dtChunk);
dtChunk = null;
}
}
}
if (dtChunk != null)
{
dataSet.Tables.Add(dtChunk);
}
}
private static DataTable CreateDataTable(int fieldCount, int tableNumber)
{
DataTable dt = new DataTable("tbl_" + tableNumber);
for(int i = 0; i < fieldCount; i++)
{
dt.Columns.Add("Column_" + i);
}
return dt;
}
没有理由一开始就使用 DataTable。
使用SqlBulkCopy.WriteToServer(IDataReader)重载,您可以将整个文件直接流式传输到 SQL Server。 如果您不想在单个事务中加载所有行,请使用SqlBulkCopy.BatchSize 。
例如
using (var sr = new StreamReader(filePath))
using (CsvReader csv = new CsvReader(sr, false, delimiter, '\"', '\0', '\0', ValueTrimmingOptions.All, 65536))
{
bulkCopy.WriteToServer(csv);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.