C#中ListView多行数据插入数据库出现重复插入问题
问题分析与修复方案
嘿,我一眼就瞅出问题所在了!你的代码里嵌套了两层循环,这正是导致重复插入的元凶:
- 外层的
foreach已经在遍历ListView里的每一行数据了 - 但你又加了一个内层的
for循环,循环次数等于ListView的总行数(listViewPOS.Count)
举个例子,如果你的ListView有3行数据,外层循环会跑3次,每次内层循环又跑3次,最终每一行数据都会被插入3次,自然就出现了三倍重复的情况!
基础修复版本
直接删掉内层的for循环就可以解决重复问题,让每一行数据只插入一次:
foreach(ListViewItem ItemRow in this.listViewPOS.Items) { SQLConn.sqL = "INSERT INTO OrderDetails(ProductID, OrderID, SRP, Quantity, Discount, Total) VALUES('" + ItemRow.SubItems[0].Text + "'," + "'" + OrderID + "', '" + ItemRow.SubItems[3].Text + "', '" + ItemRow.SubItems[4].Text + "', '" + ItemRow.SubItems[5].Text + "', '" + ItemRow.SubItems[6].Text + "')"; SQLConn.ConnDB(); SQLConn.cmd = new SqlCommand(SQLConn.sqL, SQLConn.conn); SQLConn.cmd.ExecuteNonQuery(); }
更安全的优化版本
不过这里必须提醒你:直接拼接SQL字符串存在SQL注入风险,而且如果数据里包含单引号这类特殊字符,会直接导致SQL执行报错。推荐使用参数化查询来避免这些问题,代码如下:
foreach(ListViewItem ItemRow in this.listViewPOS.Items) { SQLConn.sqL = "INSERT INTO OrderDetails(ProductID, OrderID, SRP, Quantity, Discount, Total) VALUES(@ProductID, @OrderID, @SRP, @Quantity, @Discount, @Total)"; SQLConn.ConnDB(); SQLConn.cmd = new SqlCommand(SQLConn.sqL, SQLConn.conn); // 添加参数,注意根据实际字段类型调整SqlDbType SQLConn.cmd.Parameters.Add("@ProductID", SqlDbType.VarChar).Value = ItemRow.SubItems[0].Text; SQLConn.cmd.Parameters.Add("@OrderID", SqlDbType.VarChar).Value = OrderID; SQLConn.cmd.Parameters.Add("@SRP", SqlDbType.Decimal).Value = decimal.Parse(ItemRow.SubItems[3].Text); SQLConn.cmd.Parameters.Add("@Quantity", SqlDbType.Int).Value = int.Parse(ItemRow.SubItems[4].Text); SQLConn.cmd.Parameters.Add("@Discount", SqlDbType.Decimal).Value = decimal.Parse(ItemRow.SubItems[5].Text); SQLConn.cmd.Parameters.Add("@Total", SqlDbType.Decimal).Value = decimal.Parse(ItemRow.SubItems[6].Text); SQLConn.cmd.ExecuteNonQuery(); }
另外还有个小优化:可以把数据库连接的打开和关闭放在循环外面,避免重复打开关闭连接,提升性能:
SQLConn.ConnDB(); using(SqlCommand cmd = new SqlCommand("", SQLConn.conn)) { cmd.CommandText = "INSERT INTO OrderDetails(ProductID, OrderID, SRP, Quantity, Discount, Total) VALUES(@ProductID, @OrderID, @SRP, @Quantity, @Discount, @Total)"; // 提前定义参数,循环内只赋值 cmd.Parameters.Add("@ProductID", SqlDbType.VarChar); cmd.Parameters.Add("@OrderID", SqlDbType.VarChar); cmd.Parameters.Add("@SRP", SqlDbType.Decimal); cmd.Parameters.Add("@Quantity", SqlDbType.Int); cmd.Parameters.Add("@Discount", SqlDbType.Decimal); cmd.Parameters.Add("@Total", SqlDbType.Decimal); foreach(ListViewItem ItemRow in this.listViewPOS.Items) { cmd.Parameters["@ProductID"].Value = ItemRow.SubItems[0].Text; cmd.Parameters["@OrderID"].Value = OrderID; cmd.Parameters["@SRP"].Value = decimal.Parse(ItemRow.SubItems[3].Text); cmd.Parameters["@Quantity"].Value = int.Parse(ItemRow.SubItems[4].Text); cmd.Parameters["@Discount"].Value = decimal.Parse(ItemRow.SubItems[5].Text); cmd.Parameters["@Total"].Value = decimal.Parse(ItemRow.SubItems[6].Text); cmd.ExecuteNonQuery(); } } // 记得根据你的ConnDB方法逻辑处理连接关闭
这样不仅解决了重复插入的问题,还让代码更安全、性能更好。
内容的提问来源于stack exchange,提问作者nico chua
相关产品推荐
相关产品推荐

