如何在While循环中更新数据表?循环内更新操作失败求助
问题分析与修复方案
你的代码无法完成更新的核心原因是在同一个数据库连接上,同时打开了DataReader读取数据和执行更新操作,PostgreSQL的连接不支持这种并发操作,另外代码还存在SQL注入、资源泄漏等问题,下面是具体修复:
主要问题点
- 连接资源冲突:当
DataReader处于活跃状态时,同一个连接不能执行其他SQL操作,直接创建新的Command执行ExecuteNonQuery会触发错误。 - 硬编码SQL字符串:直接拼接
mbarcode、mbarcoderr到SQL里,存在SQL注入风险,同时可能因为字符转义问题导致语句执行失败。 - 资源未正确释放:
PgSqlCommand、DataReader没有使用using语句,容易造成数据库连接或资源泄漏。 - 整数除法截断:
productqty/linkqtyy是整数除法,若需要精确的商(比如小数),结果会被强制截断。
修复后的代码
try { // 先查询出所有需要处理的数据,关闭DataReader后再执行更新 List<(int LinkQty, string MBarcode)> linkProducts = new List<(int, string)>(); // 使用using自动释放Command和DataReader资源 using (var cm = new PgSqlCommand("SELECT linkqty, mbarcode FROM public.tb_linkproduct WHERE barcode = @barcode", cn)) { cm.Parameters.AddWithValue("@barcode", mbarcode); using (var dr = cm.ExecuteReader()) { while (dr.Read()) { int linkqtyy = dr.GetInt32(0); string mbarcoderr = dr.GetString(1); linkProducts.Add((linkqtyy, mbarcoderr)); } } // DataReader在这里自动关闭 } // 遍历查询结果,执行更新操作 foreach (var item in linkProducts) { // 若需要小数结果,可改为(double)productqty / item.LinkQty int asd = productqty / item.LinkQty; using (var updateCmd = new PgSqlCommand("UPDATE tb_product SET productqty = @productqty WHERE barcode = @barcode", cn)) { updateCmd.Parameters.AddWithValue("@productqty", asd); updateCmd.Parameters.AddWithValue("@barcode", item.MBarcode); updateCmd.ExecuteNonQuery(); } } } catch (Exception ex) { // 建议添加日志记录,方便排查问题,比如写入日志文件或控制台 // Console.WriteLine($"更新失败:{ex.Message}"); throw; }
关键修复说明
- 分离查询与更新操作:先把所有需要处理的数据读取到内存集合中,关闭
DataReader后再执行更新,避免连接资源冲突。 - 全参数化SQL:所有变量都通过
Parameters传递,彻底避免SQL注入,同时解决字符转义问题。 - using语句管理资源:
PgSqlCommand和DataReader都用using包裹,确保资源自动释放,避免泄漏。 - 优化数据读取:使用
dr.GetInt32、dr.GetString代替Convert,更高效且类型安全。 - 完善异常处理:添加日志记录(示例中注释部分),方便定位具体错误。
内容的提问来源于stack exchange,提问作者NK KOUNMANY
相关产品推荐
相关产品推荐

