阅读大活追加CSV和更新SQL Server C#

cu6pst1q  于 8个月前  发布在  SQL Server
关注(0)|答案(1)|浏览(79)

我试图读取常数追加csv文件[可能是在频率,如果15-30秒];(从1行开始,直到大约结束。超过500000行,随机添加行数),并插入数据到SQL Server,避免重复,缓慢和流入性能。
我使用.NET和C#作为主要语言。有没有C# / .NET方法可以帮助BULK只从CSV中删除特定的列?
当我尝试下面的代码时,它需要自己的时间来更新记录,这会影响性能,并且应用程序处于不响应模式。

private void btnPlxl_Click(object sender, EventArgs e)
{
    this.openFileDialog1 = new OpenFileDialog();
    this.openFileDialog1.ShowDialog();

    string fn;

    fn = this.openFileDialog1.FileName;
    MessageBox.Show("Selected file :" + fn);

    string connectionString;

    SqlConnection conn;
    connectionString = @"Data Source=VKB_LAP_KIRAN\SQLEXPRESS; Initial Catalog=ExpoProCli; User ID=sa;Password=Kiran@123";

    conn = new SqlConnection(connectionString);
    conn.Open();

    MessageBox.Show("Connection opened");

    //  SELECT* FROM tbl_PS03File
    // BULK INSERT tbl_PS03file from "D:\F_PS03_06760_19102023.CSV" WITH(FORMAT = 'CSV');
    //DATAFILETYPE = 'char'.

    string sqlString = "BULK INSERT tbl_BOFile FROM 'D:\\pl.csv' WITH(FORMAT = 'CSV')";

    SqlCommand command = new SqlCommand(sqlString, conn);
    command.ExecuteNonQuery();

    MessageBox.Show("Bulk Inserted BackOffice File");

    conn.Close();
    MessageBox.Show("Connection Closed");
}

字符串

vfhzx4xs

vfhzx4xs1#

你在这里提出了三个概念:

  • BULK ®特定型号
  • BULK色谱柱特定色谱柱
  • UI线程锁定(* 应用程序进入无响应模式 *)

第三个概念超出了范围,它本身是一个定义良好的主题。最佳实践将取决于您的运行时:

为了避免重复阅读文件,我们需要保留行号引用。如果文件写入过程是流式字符,而不是整行写入追加,那么我们应该首先获得行数,以确定我们应该尝试读取的最后一行,否则我们可以根据命令影响的记录数追加行计数器。

BULK INSERT (Transact-SQL)

  • FIRSTROW = first_row指定要加载的第一行的行号。默认值为指定数据文件中的第一行。FIRSTROW从1开始。
  • LASTROW = last_row指定要加载的最后一行的编号。默认值为0,表示指定数据文件中的最后一行。

一个简单的实现,假设行是作为整行追加的,看起来像这样,注意我们在button click方法之外保留了对LastRow的引用:

private long LastRow { get;set; } = 1; //Start at line 1, use 2 if you want to skip header rows
...

private void btnPlxl_Click(object sender, EventArgs e)
{
    ...

    string sqlString = $@"
        BULK INSERT tbl_BOFile 
        FROM 'D:\pl.csv' 
        WITH(FORMAT = 'CSV', FIRSTROW = {LastRow})
    ";
    SqlCommand command = new SqlCommand(sqlString, conn);
    var rows = command.ExecuteNonQuery();
    LastRow += rows;
    
    MessageBox.Show("Bulk Inserted BackOffice File");
    conn.Close();
    MessageBox.Show("Connection Closed");
}

字符串
特定列的问题应该会改善SQL Server的执行时间,但是需要从文件中读取相同数量的字节到SQL Server中,因此根据您排除的列数以及时间丢失的位置,结果可能会有所不同。
这篇文章探讨了BULK INSERT into specific columns的一个简单解决方案:
最简单的方法是创建一个从目标表中复制的视图,列出你希望数据转到的列,按照它们在源文件中出现的顺序。然后BULK复制到你的视图中,而不是直接复制到表中。
然而,这依赖于SQL加载的文件中的列与目标表匹配,这意味着您仍然需要操作文件,或者您批量插入到临时表或staging表中,然后将这些行投影到 live 表中。
一种替代直接从活动文件中插入的方法,(IMO是一个更健壮的解决方案)是编写一个函数,将行提取到一个临时文件中,然后在将其移交给SQL之前,您还可以操作列。SQL Server可以独占访问该文件,而且文件大小也会小得多,而且一致。这将有助于减少争用,因为从文件本身阅读行不会锁定文件太长时间,我们可以处理重试如果数据库执行中存在其他暂时性问题。
看看这个相关的帖子,关于从共享访问的文件中阅读:Read Changes on a text file dynamically c#

相关问题