C# 基于编辑后DataGridView数据更新SQL表的最优实践咨询
C#小批量数据表更新最优实践及实现方案
方案选型建议
优先选择参数化批量更新方案,绝对不推荐先删除再插入的做法,原因如下:
- 删除再插入会产生大量不必要的数据库日志,性能远低于直接更新
- 若表存在外键约束,删除操作会直接触发约束报错,流程无法执行
- 自增主键、行版本戳、数据库默认值字段会在重插时被覆盖,破坏原有数据一致性
- 事务容错性极低,若删除后插入环节出错,会直接导致对应行数据丢失
现有代码问题修复
你当前的代码存在2个明显问题:
- 字符串拼接SQL存在SQL注入风险
- 数据库连接未做资源释放,可能引发连接泄漏
修复后的代码如下:
public DataTable GetSingleTable(string sTableName, string sGetConnString, string sBranchID) { DataTable dtTabletoReturn = new DataTable(); // 用参数化查询避免SQL注入 string sCommand = $"SELECT * FROM {sTableName} WHERE BranchID = @BranchID"; // using会自动释放连接资源,不需要手动Close using (SqlConnection sqlConnection = new SqlConnection(sGetConnString)) { SqlDataAdapter sqlOilAdapter = new SqlDataAdapter(sCommand, sqlConnection); // 添加参数 sqlOilAdapter.SelectCommand.Parameters.AddWithValue("@BranchID", sBranchID); sqlOilAdapter.Fill(dtTabletoReturn); } return dtTabletoReturn; }
具体实现方案
方案1:SqlDataAdapter自动更新(最简单,适合100条级别的小表)
直接利用SqlCommandBuilder自动生成增删改命令,不需要手动写SQL,代码量极小:
public void SaveTableChanges(DataTable dtModified, string sTableName, string sGetConnString, string sBranchID) { string sCommand = $"SELECT * FROM {sTableName} WHERE BranchID = @BranchID"; using (SqlConnection sqlConnection = new SqlConnection(sGetConnString)) { SqlDataAdapter sqlOilAdapter = new SqlDataAdapter(sCommand, sqlConnection); sqlOilAdapter.SelectCommand.Parameters.AddWithValue("@BranchID", sBranchID); // 自动生成对应的INSERT/UPDATE/DELETE命令 SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(sqlOilAdapter); // 直接提交DataTable的修改到数据库 sqlOilAdapter.Update(dtModified); } }
注意:使用该方案需要保证查询的表设置了主键,否则SqlCommandBuilder无法自动生成更新条件。
这个方案会自动识别DataTable里新增、修改、删除的行,分别执行对应的SQL,完全匹配你的需求。
方案2:表值参数+UPDATE FROM(高性能,可扩展到万行级数据)
如果你想要自己实现类似SQL中UPDATE FROM的批量更新逻辑,可以用SQL Server的表值参数(TVP)实现:
- 首先在SQL Server中创建对应的表值类型:
CREATE TYPE YourTableType AS TABLE ( -- 字段和你要更新的表结构、主键保持一致 ID INT PRIMARY KEY, Column1 NVARCHAR(50), Column2 INT, BranchID VARCHAR(50) )
- C#端代码实现:
public void BatchUpdateTable(DataTable dtModified, string sGetConnString) { using (SqlConnection conn = new SqlConnection(sGetConnString)) { conn.Open(); string updateSql = @" UPDATE t SET t.Column1 = tvp.Column1, t.Column2 = tvp.Column2 FROM 你的目标表 t INNER JOIN @ChangeTable tvp ON t.ID = tvp.ID WHERE t.BranchID = tvp.BranchID "; using (SqlCommand cmd = new SqlCommand(updateSql, conn)) { // 传入表值参数 SqlParameter param = cmd.Parameters.AddWithValue("@ChangeTable", dtModified); param.SqlDbType = SqlDbType.Structured; param.TypeName = "YourTableType"; // 和你SQL里建的表值类型名一致 cmd.ExecuteNonQuery(); } } }
这个方案就是你要的C#端实现UPDATE FROM批量更新的方式,性能比单条UPDATE高很多,就算后续数据量涨到几千上万条也能hold住。
内容的提问来源于stack exchange,提问作者Stef
相关产品推荐
相关产品推荐

