【问题标题】:Efficient Way to Update a lot of Rows from C#从 C# 更新大量行的有效方法
【发布时间】:2016-10-01 04:41:38
【问题描述】:

我有一个程序,我在其中打开SqlConnection,加载对象列表,修改每个对象的值,然后更新 SQL Server 数据库中的行。因为修改需要字符串解析,所以我无法使用纯 T-SQL 进行。

现在我正在遍历对象列表,并在每次迭代中运行 SQL 更新。这似乎效率低下,我想知道是否有更有效的方法来使用 LINQ

该列表称为UsageRecords。我正在更新的值是MthlyConsumption

这是我的代码:

foreach (var item in UsageRecords)
{
    string UpdateQuery = @"UPDATE tbl810CTImport 
                           SET MthlyConsumption = " + item.MthlyConsumption +
                           "WHERE ID = " + item.Id;
    SqlCommand update = new SqlCommand(UpdateQuery, sourceConnection);
    update.ExecuteNonQuery();
}

【问题讨论】:

  • 与您的问题无关:use parameterized sql,以避免注入并阻止坏字符破坏查询(如果您要插入字符串,则像 ' 字符)
  • 与您的问题相关:see this post。我想这就是你要找的。​​span>
  • 谢谢,这是一个很好的观点。在我测试的时候,代码中只有 SQL 文本。
  • @JohnCarpenter 感谢您的链接

标签: c# sql-server linq


【解决方案1】:

试试这个:

string UpdateQuery = @"UPDATE tbl810CTImport SET MthlyConsumption = @consumption WHERE ID = @itemId";
var update = new SqlCommand(UpdateQuery, sourceConnection);
update.Parameters.Add("@consumption", SqlDbType.Int); // Specify the correct types here
update.Parameters.Add("@itemId", SqlDbType.Int); // Specify the correct types here
foreach (var item in UsageRecords)
{
    update.Parameters[0].Value = item.MthlyConsumption; 
    update.Parameters[1].Value = item.Id;
    update.ExecuteNonQuery();
}

应该更快,因为:

  • 您不必每次都创建命令。
  • 您不会每次都创建一个新字符串(连接)
  • 不会在每次迭代时解析查询(只需更改参数值)。
  • 它会cache the execution plan。 (感谢评论中的@JohnCarpenter)

【讨论】:

  • 另请注意SQL will cache the execution plan,使用这种方法可以加快速度
  • @JohnCarpenter 谢谢。我知道这件事,但找不到来源。我已经相应地编辑了答案。
  • 根据性能与您愿意投入的开发工作量,批量插入临时表并像我的回答一样运行单个更新语句将是最快的。
【解决方案2】:

你可以使用

  1. SqlDataAdapter - 见How to perform batch update in Sql through C# code

或者我之前所做的是以下之一:

  1. 拆除有问题的 ID,然后重新批量插入

  1. 将 ID + 新值批量插入临时表,并在 SQL Server 上更新表:

update u set u.MthlyConsumption = s.MthlyConsumption from tbl810CTImport u inner join staging s on u.id = s.id

【讨论】:

    【解决方案3】:

    在这种情况下,您无法编写一条更新语句来涵盖所有基础,最好将您的语句分批并一次运行多个。

    var commandSB = new StringBuilder();
    int batchCount = 0;
    
    using (var updateCommand = sourceConnection.CreateCommand())
    {
        foreach (var item in UsageRecords)
        {
            commandSB.AppendFormat(@"
                UPDATE tbl810CTImport 
                SET MthlyConsumption = @MthlyConsumption{0}
                WHERE ID = @ID{0}", 
                batchCount
            );
    
            updateCommand.Parameters.AddWithValue(
                "@MthlyConsumption" + batchCount,
                item.MthlyConsumption
            );
    
            updateCommand.Parameters.AddWithValue(
                "@ID" + batchCount,
                item.MthlyConsumption
            );
    
            if (batchCount == 500) {
                updateCommand.CommandText = commandSB.ToString();
                updateCommand.ExecuteNonQuery();
    
                commandSB.Clear();
                updateCommand.Parameters.Clear();
                batchCount = 0;
            }
            else {
                batchCount++;
            }
        }
    
        if (batchCount != 0) {
            updateCommand.ExecuteNonQuery();
        }
    }
    

    【讨论】:

      【解决方案4】:

      应该就这么简单。 . .

      private void button1_Click(object sender, EventArgs e)
              {
                  SqlConnection con = new SqlConnection("Server=YourServerName;Database=YourDataBaseName;Trusted_Connection=True"); 
      
                  try
                  {
                      //cmd new SqlCommand( "UPDATE Stocks 
                      //SET Name = @Name, City = @cit Where FirstName = @fn and LastName = @add";
      
                      cmd = new SqlCommand("Update Stocks set Ask=@Ask, Bid=@Bid, PreviousClose=@PreviousClose, CurrentOpen=@CurrentOpen Where Name=@Name", con);
                      cmd.Parameters.AddWithValue("@Name", textBox1.Text);
                      cmd.Parameters.AddWithValue("@Ask", textBox2.Text);
                      cmd.Parameters.AddWithValue("@Bid", textBox3.Text);
                      cmd.Parameters.AddWithValue("@PreviousClose", textBox4.Text);
                      cmd.Parameters.AddWithValue("@CurrentOpen", textBox5.Text);
                      con.Open();
                      int a = cmd.ExecuteNonQuery();
                      if (a > 0)
                      {
                          MessageBox.Show("Data Updated");
                      }
                  }
                  catch (Exception ex)
                  {
                      MessageBox.Show(ex.Message);
                  }
                  finally
                  {
                      con.Close();
                  }
              }
      

      更改代码以满足您的需要。

      【讨论】:

        猜你喜欢
        • 2015-11-30
        • 2018-09-03
        • 1970-01-01
        • 1970-01-01
        • 2013-08-22
        • 1970-01-01
        • 2014-05-19
        • 2023-04-01
        • 1970-01-01
        相关资源
        最近更新 更多