C# 由于没有Sqlserver数组参数,那么';这是最好的方式吗?

C# 由于没有Sqlserver数组参数,那么';这是最好的方式吗?,c#,asp.net,sql-server,sql-server-2005,stored-procedures,C#,Asp.net,Sql Server,Sql Server 2005,Stored Procedures,我需要在sqlserver中创建多个记录,每个记录在A列中具有相同的值,但在B列中具有唯一的值。我在数组中具有B列的值 我使用的是VS2008、aspnet、c#3.5、SQLServer2005 我过得好吗 备选案文1 从c#代码对sqlserver中的存储过程进行1次调用,然后在tsql中的存储过程中执行所有处理工作 这将涉及将c#数组中的所有值组合成一个逗号分隔的字符串,并将该字符串作为参数传递给tsql,然后将该字符串循环并分解为各个值,并为每个值插入一条记录,所有这些都在存储过程中 从

我需要在sqlserver中创建多个记录,每个记录在A列中具有相同的值,但在B列中具有唯一的值。我在数组中具有B列的值

我使用的是VS2008、aspnet、c#3.5、SQLServer2005

我过得好吗

备选案文1

从c#代码对sqlserver中的存储过程进行1次调用,然后在tsql中的存储过程中执行所有处理工作

这将涉及将c#数组中的所有值组合成一个逗号分隔的字符串,并将该字符串作为参数传递给tsql,然后将该字符串循环并分解为各个值,并为每个值插入一条记录,所有这些都在存储过程中

从我所看到的情况来看,如果需要,这将涉及到简单的回滚,但在tsql中处理字符串非常笨拙

备选案文2

在c#中执行循环,并将数据作为sqlparams从c#每次一条记录传递到存储的进程,以插入每条记录

Ie,foreach(myarray中的int键)…插入一条记录

我可以在睡眠中做这个代码,但是如果处理过程中发生了什么,我怎么能回滚呢?我应该在单个连接中进行循环。打开和连接。关闭


有人有其他选择吗?

本主题在这里有详细介绍:

两个选项都有各自的优点(选项1是一个单程往返,选项2不使用hokey字符串处理),但我可能最终选择选项2。选项1的大小限制为
varchars
(8000,除非您使用
varchar(MAX)
;我不知道逗号分隔的
varchar(MAX)
字符串非常长,性能会如何)

至于回滚,是的,只需在单个打开的连接上执行所有操作,并使用
SqlTransaction
对象

例如

using(SqlConnection conn = new SqlConnection("connection string"))
{
    conn.Open();

    using(SqlTransaction trans = conn.BeginTrasnaction())
    {
        try
        {
            using(SqlCommand cmd = new SqlCommand("command text", conn, trans))
            {
                SqlParameter aParam = new SqlParameter("a", SqlDbType.Int);
                SqlParameter bParam = new SqlParameter("b", SqlDbType.Int);

                cmd.Parameters.Add(aParam);
                cmd.Parameters.Add(bParam);

                aParam.Value = 1;

                foreach(int value in bValues)
                {
                    bValue = value;

                    cmd.ExecuteNonQuery();
                }
            }

            trans.Commit();
        }
        catch
        {
            trans.Rollback();

            throw; // so the exception can propogate up
        }
    }
}

实现这一点的最简单方法是使用选项1:将数组作为分隔字符串传递。在sql2005之前的几天里,我经常结合这个来做这件事。我将使用“|”作为分隔符传递数组

现在,我将数组序列化为XML,然后将内容插入表变量中,以便使用存储过程进行处理


我不会使用选项2,因为它会多次调用数据库。

不确定这是否完全适合您的情况,但很多时候,当我们需要将N大小的数据数组传递到存储过程中时,我们会使用临时表技巧。只有以下几行:

using (SqlConnection connection = new SqlConnection(connectionstring)) {
   connection.Open();

   string sql = "CREATE TABLE #foo (myvalue [INT]) ";
   using (SqlCommand command = connection.CreateCommand()) {
      command.CommandText = sql;
      command.CommandType = CommandType.Text;

      command.ExecuteNonQuery(); // create the temp table

      foreach (int value in myValuesList) {
         command.CommandText = "INSERT INTO #foo ([myvalue]) VALUES (" + value + ") ";

         command.ExecuteNonQuery();
      }

      command.CommandType = CommandType.StoredProcedure;
      command.CommandText = "StoredProcThatUsesFoo";

      // fill in any other parameters

      command.ExecuteNonQuery();
   }
}

如果您想在C#中的循环中执行多个插入,请查看TransactionScope。这将允许您将对存储过程的多个调用回滚到具有回滚功能的事务中。另一种选择是,您可以将数组作为XML传递,在存储的进程中,您可以将XML分解到临时表中,以便在进程中使用


您应该做的最后一件事是将升级到下一版本SQL server的原因添加到您的愿望列表中。随着愿望清单的增加,你花钱升级的理由变得更容易了。

我希望有一个简单的答案。哦,好吧。谢谢你的链接。Erland的文章多年来一直是这个主题的参考资料,如果你在这个领域冒险,这是一本必读的书。真正简单的答案是:升级到SQL Server 2008并使用表值参数:-)@Jab:Thank,但你实际上并没有+1 me;)如果数组“B”(如问题中所述)非常大,那么这一开始的代价会很高-我并不知道有更好的解决方案,但这可能是需要记住的。如果无法轻松定义字符串大小的上限,则传递带分隔符的字符串可能会很麻烦。+1-我已使用split函数将数组传递给存储过程。尽管如此,我还是迫不及待地想升级到SQL2008并改用XML。您还在SQL Server 2005上使用sp_XML_preparedocument吗?当它支持XQuery等时,SQL 2005和2008中都提供了sp_xml_PreparedDocument。循环拆分功能非常慢,请使用以下数字表方法:+1我的想法-升级到SQL server 2008,并一次性解决此问题:-)