从 C# SQLCLR 存储过程批量插入 SQL 表的最快方法

Hem*_*dia 3 c# sql-server import sqlclr sql-server-2008

我有一个 C# SQLCLR 存储过程,其中首先将数据填充到一些字典中并进行计算,然后将输出存储在其他一些字典中。

由于使用了字典,该计算完成得非常快,并且完全证明了我需要使用 CLR 存储过程而不是普通的 SQL 存储过程。

然而,我必须将这些输出字典中的数据保存在 SQL 中的某些表中,这部分花费了很多时间,并且满足了我对整个 SQLCLR 过程更快的需求。

我必须迭代每个输出字典的每个键,然后必须创建插入查询,然后必须按以下方式运行 ExecuteNonQuery: 在此输入图像描述

那么我该如何改进我的这种方法,以便在插入数据时不需要花费时间。我无法使用SqlBulkCopy,因为它不接受进程内上下文连接(即"Context Connection = true;")作为连接字符串。那么还有其他更快的方法可用吗?提前致谢。

Sol*_*zky 5

您有几个选择:

  1. 创建用户定义表类型 (UDTT) 和接受该 UDTT 作为参数(即表值参数 (TVP))的 T-SQL 存储过程。由于您已经在集合中拥有数据,因此绝对不要创建单独的集合DataTable来将该数据传输到其中,因为这只是浪费时间、内存和 CPU。IEnumerable<SqlDataRecord>您可以通过创建一个返回、 使用和 用作表示 UDTT 的yield return;值的方法,将其本机集合中的数据直接流式传输到 TVP 中。SqlParameter我这里有两个例子:

  2. 如果只有 1 个表要填充(因此有 1 个结果集),则可以将集合作为结果集从存储过程输出并按如下方式使用:

    INSERT INTO schema.table (column_list)
      EXEC schema.SQLCLR_stored_procedure @param1, ....;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如果只有 1 个表要填充(因此有 1 个结果集),并且您没有在上下文连接上执行任何违反标量函数规则的操作,那么您可以尝试将 SQLCLR 存储过程更改为 TVF,返回IEnumerable,并迭代返回viayield return;以将其流出来。几年前,我在 SQL Server Central 上写了一篇文章,其中包含这样的示例:具有全流式处理的 CLR 表值函数示例 (STVF / TVF)