C# SqlBulkCopy将数据表添加到数据集时复制它们

C# SqlBulkCopy将数据表添加到数据集时复制它们,c#,sql-server,asynchronous,sqlbulkcopy,C#,Sql Server,Asynchronous,Sqlbulkcopy,我希望将csv中的值解析为数据表块,将它们添加到数据集,然后使用SQLBulkCopy将数据表插入SQL中的单个表中。原始csv的范围从4GB到8GB,我需要避免将整个内容读入内存,从而避免分块。我松散地将我的分块建立在这个基础上。我使用它来解析csv值 一旦数据表被添加到数据集中,我希望在创建下一个数据表的同时使用SqlBulkCopy将其插入到我的SQL表中。SqlBulkCopy完成后,我想删除datatable以释放内存 我的第一个想法是在不等待的情况下异步运行chunking方法,然后

我希望将csv中的值解析为数据表块,将它们添加到数据集,然后使用SQLBulkCopy将数据表插入SQL中的单个表中。原始csv的范围从4GB到8GB,我需要避免将整个内容读入内存,从而避免分块。我松散地将我的分块建立在这个基础上。我使用它来解析csv值

一旦数据表被添加到数据集中,我希望在创建下一个数据表的同时使用SqlBulkCopy将其插入到我的SQL表中。SqlBulkCopy完成后,我想删除datatable以释放内存

我的第一个想法是在不等待的情况下异步运行chunking方法,然后运行while循环,检查数据集中是否存在下一个datatable。如果datatable存在,则大容量复制。如果datatable行数小于行限制,则它是最后一个块,并在循环时停止

我走错方向了吗?如果没有,我怎么能做这样的事情

        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);
            }
        }
stringfilepath=@“C:\Users\user\Downloads\Testing\file-Copy.csv”;
数据集ds=新数据集();
bool continueInsert=true;
int rowLimit=100000;
int tableNumber=0;
//启动此循环,但不要等到它完成后再启动while循环
ChunkCSV(文件路径、ds、行限制);
//如果datatable存在,则运行SqlBulkCopy
while(continueInsert)
{
if(ds.表格包含(“tbl”+表格编号))
{
DataTable DataTable=ds.Tables[“tbl_”+表格编号];
//SqlBulkCopy数据表代码在此处
if(ds.Tables[“tbl_”+TABLENAMER].Rows.Count
以下是我的分块代码:

    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;
    }
private static void ChunkCSV(字符串文件路径、数据集数据集、整数行限制)
{
字符分隔符=',';
DataTable dtChunk=null;
int tableNumber=0;
int chunkRowCount=0;
bool firstLineOfChunk=true;
使用(var sr=newstreamreader(filePath))
使用(CsvReader csv=new CsvReader(sr、false、分隔符“\”、“\0”、“0”、ValueTrimmingOptions.All、65536))
{
int fieldCount=csv.fieldCount;
string[]行=新字符串[fieldCount];
//必要时添加字段
csv.MissingFieldAction=MissingFieldAction.ReplaceByEmpty;
而(csv.ReadNextRecord())
{
如果(第一行)
{
firstLineOfChunk=false;
dtChunk=CreateDataTable(fieldCount,tableNumber);
}
DataRow DataRow=dtChunk.NewRow();
csv.CopyCurrentRecordTo(行);
对于(int f=0;f
没有理由一开始就使用数据表

使用重载,您可以将整个文件直接流式传输到SQL Server。如果不希望在单个事务中加载所有行,请使用重载

乙二醇


没有理由一开始就使用DataTable

使用重载,您可以将整个文件直接流式传输到SQL Server。如果不希望在单个事务中加载所有行,请使用重载

乙二醇


将整个文件直接流式传输到SQL Server不会导致将整个文件读取到内存中,而OP正试图避免这种情况吗?不会。只要IDataReader实现逐行读取文件,它就会一直流式传输到SQL Server。因此,您是说也不需要
CsvReader
,而所有这些都不是CSV解析是在SQL中完成的吗?不,CsvReader仍在进行解析,并实现IDataReader接口,SqlBulkCopy知道如何从中读取。难以置信!如此简单。再次感谢。将整个文件直接流式传输到SQL Server不会导致将整个文件读取到内存中,这是OP试图避免的吗?不,只要不IDataReader实现逐行读取文件,它将一直流式传输到SQL Server。因此,您是说也不需要
CsvReader
,所有CSV解析都是在SQL中完成的?不,CsvReader仍然进行解析,并实现IDataReader接口,SqlBulkCopy知道如何从.Inc读取该接口重拨!很简单。再次感谢。
using (var sr = new StreamReader(filePath))
using (CsvReader csv = new CsvReader(sr, false, delimiter, '\"', '\0', '\0', ValueTrimmingOptions.All, 65536))
{
    bulkCopy.WriteToServer(csv);
}