更新一批记录的最简单方法是只进行一次访问。
更新一批记录的最简单方法是只进行一次访问。
通常,您会在循环内一次更新一条记录。如果有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) { //处理异常 } }
请不要对这个问题投票。
问题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();
问题的出现原因:
在上述代码中,需要对一个批量的记录进行更新操作。原始的实现方式是使用一个循环,每次循环都会发送一个独立的更新语句到数据库,这样就会导致需要多次与数据库进行通信,效率较低。
解决方法:
为了提高效率,需要找到一种方法可以在只进行一次数据库通信的情况下完成批量记录的更新操作。一种可行的解决方法是使用 StringBuilder 类来构建一个包含所有更新语句的字符串,然后将其作为一个整体发送到数据库。
具体步骤如下:
1. 创建一个 StringBuilder 对象,用于存储所有的更新语句。
2. 使用循环遍历需要更新的记录,并在每次循环中执行以下步骤:
a. 使用 AppendLine 方法将更新语句添加到 StringBuilder 对象中。
b. 使用参数化查询的方式设置更新语句中的参数值。
3. 将 StringBuilder 对象转换为字符串,并将其设置为 SqlCommand 对象的 CommandText 属性。
4. 打开数据库连接。
5. 调用 SqlCommand 的 ExecuteNonQuery 方法执行更新操作。
6. 在 finally 块中释放 SqlCommand 对象和关闭数据库连接。
通过使用 StringBuilder 类,可以将多个更新语句合并成一个字符串,从而减少了与数据库的通信次数,提高了更新操作的效率。
最终,通过以上的优化,可以以一次数据库通信的方式完成对批量记录的更新操作。
最简单的方法是使用存储过程和表值参数来更新一批记录。这种方法的性能最好。另一种简单的方法是使用StringBuilder将SQL语句拼接在一起,但是要注意长度的限制。前一种方法更具可扩展性和正确性。StringBuilder的长度限制是由SQL Server引入的。在SQL Server中,这些限制非常高。
解决方法:
- 使用存储过程和表值参数来更新一批记录,这是最好的解决方法。这种方法更具可扩展性和正确性。
- 可以使用StringBuilder来拼接SQL语句,但要注意长度的限制。在SQL Server中,长度限制是由SQL Server引入的。
代码示例:
// 使用存储过程和表值参数更新一批记录 using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = new SqlCommand("UpdateRecords", connection); command.CommandType = CommandType.StoredProcedure; DataTable records = new DataTable(); records.Columns.Add("Id", typeof(int)); records.Columns.Add("Name", typeof(string)); // 添加要更新的记录到表值参数中 foreach (Record record in recordsToUpdate) { DataRow row = records.NewRow(); row["Id"] = record.Id; row["Name"] = record.Name; records.Rows.Add(row); } // 将表值参数传递给存储过程 SqlParameter parameter = command.Parameters.AddWithValue("@Records", records); parameter.SqlDbType = SqlDbType.Structured; parameter.TypeName = "dbo.RecordType"; // 执行存储过程 command.ExecuteNonQuery(); } // 使用StringBuilder拼接SQL语句 StringBuilder sql = new StringBuilder(); sql.Append("UPDATE Records SET "); sql.Append("Name = 'NewName' "); sql.Append("WHERE Id IN ("); foreach (int id in idsToUpdate) { sql.Append(id + ","); } sql.Length--; // 移除最后一个逗号 sql.Append(")"); using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = new SqlCommand(sql.ToString(), connection); command.ExecuteNonQuery(); }
以上是解决问题的方法和相应的代码示例。
使用Dapper进行批量记录更新的最简单方法是使用Dapper库,它是一个简单的.NET对象映射器。下面是一个使用Dapper进行批量记录更新的示例代码:
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); }
以上代码通过Dapper的`Execute`方法执行了一次数据库操作,实现了批量记录更新的目的。这种方法的优点是只需要进行一次数据库访问,减少了网络传输的开销,提高了效率。
这段代码的使用者表示自己还没有尝试过Dapper,但是他使用了Linq和NuGet。他的同事对Linq持有负面态度,希望保持简单。但是他认为使用Dapper的方法看起来应该能够解决问题,并且对此表示了支持。
,Dapper是一种简单且高效的.NET对象映射器,可以用于批量记录更新。通过只进行一次数据库访问,可以减少网络传输开销,提高效率。