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

时间:2017-10-13 12:08:34

标签: c# sql-server sql-server-2008 import sqlclr

我有一个C#SQLCLR存储过程,其中第一个数据填充在一些字典中并被计算,然后输出存储在其他一些字典中。

由于字典的使用,这种计算速度非常快,完全证明了我需要使用CLR存储过程而不是普通的SQL存储过程。

但是,我必须从这些输出字典中保存SQL中某些表中的数据,这部分需要花费很多时间,并且不需要整个SQLCLR proc更快。

我必须迭代每个输出字典的每个键,然后必须创建插入查询,然后必须以下列方式运行ExecuteNonQuery: enter image description here

那么我怎样才能改进这种方法,这样就不需要花时间插入数据。我无法将SqlBulkCopy用作it does not accept the in-process Context Connection(即"Context Connection = true;")作为connectionString。那么还有其他更快的方法吗?提前谢谢。

2 个答案:

答案 0 :(得分:3)

使用SqlBulkCopy Class或者您可以在User-Defined Table Type sql中创建自己的c# - 将您的数据生成为DataTable,而不是某些集合,它将与您的用户定义类型匹配,然后将DataTable作为SqlParameter传递并执行。或者您可以将您的收藏集直接添加到表值参数中,如Here所示(useDataTable == false部分)

当然,为此你应该使用sql存储过程。 sql用户定义的表类型的调用部分将如下所示:

cmd = new SqlCommand{ Connection = conn, ...
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_YourStoredProcedureName";
cmd.Parameters.Add(new SqlParameter("@UserDefinedTypeParameterName", yourDataTable));
cmd.ExecuteNonQuery();

答案 1 :(得分:2)

您有几个选择:

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

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

    INSERT INTO schema.table (column_list)
      EXEC schema.SQLCLR_stored_procedure @param1, ....;
    
  3. 如果只有一个表要填充(因此有1个结果集),如果您没有通过Context Connection做任何违反标量函数规则的事情,那么你可以尝试将SQLCLR存储过程更改为TVF,返回IEnumerable,并通过yield return;迭代返回以将其流出。几年前我在SQL Server Central上写了一篇文章:CLR Table-Valued Function Example with Full Streaming (STVF / TVF)