DataGridView循环查询重复记录异常 删除重复行后仍触发重复告警
问题原因
- 核心逻辑错误:
mukerrer方法的校验逻辑只会保留最后一行的校验结果,后序行的校验状态会直接覆盖前面的结果;同时你使用的全局durum变量没有在方法开头重置状态,上次校验留下的false值会一直残留,就算删除重复行后也不会自动更新。 - 空行触发异常:默认开启
AllowUserToAddRows属性的DataGridView会在末尾自带一个空的待输入行,遍历到该行时读取barkod_no会触发空引用异常,方法直接中断,durum会保持上次的false状态,导致一直弹出重复警告。 - 存在SQL注入风险:拼接SQL字符串的写法容易被注入攻击,特殊格式下还会触发语法错误。
- 资源泄漏风险:
SqlDataReader未主动释放,频繁开关数据库连接效率低下。
修复方案
1. 重写校验方法
bool mukerrer() { // 初始默认无重复 bool hasDuplicate = false; for (int i = 0; i < dataGridView1.Rows.Count; i++) { // 跳过空的新行和值为空的行 if (dataGridView1.Rows[i].IsNewRow || dataGridView1.Rows[i].Cells["barkod_no"].Value == null) continue; long barkodNo = Int64.Parse(dataGridView1.Rows[i].Cells["barkod_no"].Value.ToString()); using (SqlCommand komut = new SqlCommand("SELECT COUNT(1) FROM STOKLAR WHERE barkod_no = @barkodNo", baglanti)) { komut.Parameters.AddWithValue("@barkodNo", barkodNo); baglanti.Open(); int count = Convert.ToInt32(komut.ExecuteScalar()); baglanti.Close(); if (count > 0) { hasDuplicate = true; // 发现重复直接跳出循环,无需校验剩余行 break; } } } // 有重复返回false,无重复返回true,和原有逻辑对齐 return !hasDuplicate; }
2. 修正提交按钮逻辑
private void simpleButton1_Click(object sender, EventArgs e) { bool durum = mukerrer(); if (durum == true) { // 用事务保证所有数据要么全插入成功要么全回滚,避免部分插入的脏数据问题 baglanti.Open(); SqlTransaction tran = baglanti.BeginTransaction(); try { for (int i = 0; i < dataGridView1.Rows.Count; i++) { if (dataGridView1.Rows[i].IsNewRow || dataGridView1.Rows[i].Cells["barkod_no"].Value == null) continue; SqlCommand komut = new SqlCommand("insert into STOKLAR(barkod_no,toplam_paket_no,paket_no,raf_id,create_date) values (@barkod_no,@toplam_paket_no,@paket_no,@raf_id,@create_date)", baglanti, tran); komut.Parameters.AddWithValue("@barkod_no", Int64.Parse(dataGridView1.Rows[i].Cells["barkod_no"].Value.ToString())); komut.Parameters.AddWithValue("@toplam_paket_no", int.Parse(dataGridView1.Rows[i].Cells["toplam_paket_no"].Value.ToString())); komut.Parameters.AddWithValue("@paket_no", int.Parse(dataGridView1.Rows[i].Cells["paket_no"].Value.ToString())); komut.Parameters.AddWithValue("@raf_id", dataGridView1.Rows[i].Cells["raf_id"].Value.ToString()); komut.Parameters.AddWithValue("@create_date", dataGridView1.Rows[i].Cells["create_date"].Value); komut.ExecuteNonQuery(); } tran.Commit(); textRaf.Text = ""; MessageBox.Show("Kayıtlar Eklenmiştir."); this.ActiveControl = textRaf; } catch (Exception ex) { tran.Rollback(); MessageBox.Show("Kayıt ekleme hatası: " + ex.Message); } finally { baglanti.Close(); } } else { MessageBox.Show("Sistemde kayıtlı olan barkod var!", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
额外优化建议
- 可以把全局的
baglanti对象改成方法内创建,用完即释放,避免连接长时间占用导致异常。 - 给
STOKLAR表的barkod_no字段加唯一索引,就算校验逻辑漏判,数据库也会阻止重复数据插入,双重保障。
内容的提问来源于stack exchange,提问作者Sinem Hür
相关产品推荐
相关产品推荐

