仅使用一次旅行更新一批记录的最简单方法是什么?

时间:2017-02-02 22:05:52

标签: c# sql sql-server

通常,您将在循环内一次更新一次。如果您有100条记录,那么您将有100次访问服务器,这是不可取的。如何通过单次往返数据库更新一组记录。

using System.Data.SqlClient;

for (int ii = 0; ii < ptList.Length; ii++)    {
    sql = @"update [CCVT].[dbo].[_tb_NCVT_Points] set PointDateTime = CONVERT(datetime, '"
    + ptList[ii]._dateDt.ToString("yyyy-MM-dd HH:mm:ss.FFF") + "', 121), PointStatus = '"
    + ptList[ii]._statStr + "', PointValue =" + ptList[ii]._valDoub.ToString() 
    + " WHERE Pointkey = '" + ptList[ii]._pointName + "'; ";
    theActiveConnection.Open();
    SqlCommand cmd = new SqlCommand(sql, theActiveConnection);
    try {
        cmd.ExecuteNonQuery();
        cmd.Dispose();
    }
    catch (Exception eX) {
       //handle exceptions
    } 
}

请不要将这个问题投下来。
问题How can I update multiple rows in a table with SQL query? 没有要求一次旅行,他们的回答没有产生一次旅行!您是否看到ExecuteNonQuery操作在循环内?那不是我的问题,那不是我的答案!

foreach (DataGridViewRow row in dataGridView2.Rows)
    {
        cm.Parameters["@Qty"].Value = row.Cells[2].Value;
        cm.Parameters["@Description"].Value = row.Cells[3].Value;
        cm.Parameters["@Price"].Value = row.Cells[4].Value;
        cm.ExecuteNonQuery();
    }
    cn.Close();

4 个答案:

答案 0 :(得分:3)

SqlCommand cmd = new SqlCommand("", theActiveConnection);
StringBuilder sql = new StringBuilder();
for (int ii = 0; ii < ptList.Length; ii++)    {
    sql.AppendLine("UPDATE [CCVT].[dbo].[_tb_NCVT_Points]"); 
    sql.AppendLine($"SET PointDateTime = CONVERT(datetime, @PointDateTime{ii}, 121), PointStatus = @PointStatus{ii}, PointValue = @PointValue{ii}");
    sql.AppendLine($"WHERE Pointkey = '@PointKey{ii};");
    cmd.Parameters.AddWithValue($"@PointDateTime{ii}",ptList[ii]._dateDt.ToString("yyyy-MM-dd HH:mm:ss.FFF"));
    cmd.Parameters.AddWithValue($"@PointStatus{ii}",ptList[ii]._statStr);
    cmd.Parameters.AddWithValue($"@PointValue{ii}",ptList[ii]._valDoub.ToString());
    cmd.Parameters.AddWithValue($"@Pointkey{ii}",ptList[ii]._pointName);

}
try {
    cmd.CommandText = sql.ToString();
    theActiveConnection.Open();
    cmd.ExecuteNonQuery();
}
catch (Exception eX) {
   //handle exceptions
} 
finally {
    cmd.Dispose();
    theActiveConnection.Close();
}

有许多方法可以解决此问题,具体取决于命令的接近程度和程度。在你的情况下,我认为这是最好的。

答案 1 :(得分:2)

表现最佳的方法是将表值参数与存储过程一起使用 https://msdn.microsoft.com/en-us/library/bb675163(v=vs.110).aspx

简单的方法是使用StringBuilder或者用分号连接SQL语句。但请注意,这在长度上有限制!!!

答案 2 :(得分:2)

直接答案由Andrew发布,但这取决于您的数据来自何处。

如果点列表已经存在于数据库中,并且您要将其查询到列表中(一个带有循环的SELECT来填充列表),然后调用大量更新,则应直接执行UPDATE FROM它将SELECT和UPDATE组合在一个语句中。一次访问服务器,网络上没有不必要的行。

答案 3 :(得分:1)

为什么不使用Dapper - .Net

的简单对象映射器
var list = ptList.select(p => new{
        DateTime = p._dateDt,
        Status = p._statStr,
        Value = p._valDoub,
        Key = p._pointName
    });
using(var connection = new SqlConnection...)
{
  connection.open()
  connection.Execute("update [CCVT].[dbo].[_tb_NCVT_Points] set PointDateTime = @DateTime, PointStatus = @Status, PointValue = @Value
 WHERE Pointkey = @Key", list);
}