【问题标题】:C# batch update to database using Stored ProcedureC# 使用存储过程批量更新数据库
【发布时间】:2011-11-30 08:38:30
【问题描述】:

我想运行我的更新存储过程来更新一个表中的两列(这个表还有许多其他列)。

目前我已经实现如下 -

foreach (Object obj in customCollection)
{
    string[] updatedValues = GetUpdatedValues(obj.Property1);

    using (SqlConnection sqlConnection = new SqlConnection(connString))
    {
         sqlConnection.Open();

         SqlParameter[] sqlParams = new SqlParameter[2];
         sqlParams[0] = new SqlParameter("@column1", SqlDbType.Float) { Value = updatedValues[0]};
         sqlParams[1] = new SqlParameter("@column2", SqlDbType.Float) { Value = updatedValues[1] };

         using (SqlCommand command = new SqlCommand("upUpdateProcedure", sqlConnection))
         {
              command.CommandType = CommandType.StoredProcedure;
              command.Parameters.AddRange(sqlParams);
              DatabaseHelper.ExecuteNonQuery(command);
         }
    }
}

所以,如您所见,上面的代码正在为集合中的每个对象调用数据库。

我浏览了几个“从 C# 到 SQL Server 的批量更新”链接,但大多数链接都建议在 C# 代码中加载表,更新表行,然后调用 DataAdapter.Update()。

但是,我只是想知道是否有任何其他已知方法可以不同地处理这种情况 - 我的意思是我不想将整个表加载到内存中,因为它还有许多其他列数据。

请指导。

【问题讨论】:

  • 将连接的打开移到foreach (Object obj in customCollection) 循环之外可能会更有效。为什么要为每次更新打开一个新连接?

标签: c# sql-server batch-updates


【解决方案1】:

我经常做的一件事是将 XML 一次性发送到 SQL。比在循环中多次调用 DB 的性能要好得多。

Jon Galloway 有一个老歌,但你可以参考的好歌 here

您只需将数据或列转换为 XML。如果你在一个类中有这些数据,那真的很简单。查看this extension method - 我不记得我在哪里找到了这段代码,所以我无法正确地归因它。

【讨论】:

    【解决方案2】:

    如果您使用的是 SQLServer 2008 或更高版本,则可以填充 DataTable,并将其作为表值参数传递给存储过程。

    关于表值参数的信息: http://www.sommarskog.se/arrays-in-sql-2008.html#TVP_in_TSQL

    stored proc 可以像访问表变量一样访问表参数,因此可以在一个块中执行更新,这对性能有好处。

    这种方法类似于 Billy Coover 的 XML 方法,但使用的是 DataTable 而不是 XML。

    【讨论】:

      【解决方案3】:

      在我看来,您正在做的事情应该可以正常工作。或者,您可以构建一个“批次”更新(每个可能有 50、100 或更多更新),并分块提交它们,但不确定这是否有助于提高性能,并且可能会降低可读性。

      您有性能问题吗? customCollection 中有多少项?

      【讨论】:

        【解决方案4】:

        是的,动态构建您的 sql 查询,是的,我知道与存储过程相比,它的性能很差,但考虑到代码中的所有连接打开和关闭开销,这可能不是一个坏主意。我还注意到,在您的代码中,您正试图尽快打开和关闭连接,这是一种很好的做法。但是,我发现当我保持打开 1 个连接以进行多次更新时,与多次打开和关闭连接相比,它要快得多。但是,由于您保持连接打开,因此缩放可能不太好。

        【讨论】:

        • 实际上,对于 SQL Server(从版本 7 开始),存储过程的性能不会比任何其他参数化 SQL 语句(不一定是动态查询)好。存在安全隐患,以及有利于存储过程的设计考虑因素,但性能不再是决定使用存储过程还是参数化 SQL 的驱动问题。
        • 哇,感谢您指出这一点。我以为所有的动态查询每次都需要sql server来解析查询,结果发现使用参数的动态查询会被缓存,和存储过程一样好
        【解决方案5】:

        从 TableAdapter 获取 DataTable(自动生成):

        FooTableAdaptor tableAdapter = new FooTableAdapter();
        FooDataTable dataTable = FooTableAdaptor.MyQuery(...);
        

        滚动浏览进行更改的 DataTable 行 - 这只是本地的。
        打电话

        tableAdapter.Update(dataTable)  
        

        一键写入变化。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多