DataGridView插入行触发异常:Collection was modified; enumeration operation might not execute
解决遍历DataTable时插入行引发的集合修改异常
你遇到的Collection was modified; enumeration operation might not execute异常,核心原因是:foreach遍历dt.Rows时,枚举器会锁定集合结构,不允许遍历过程中添加/删除元素(修改集合大小),而你在循环里调用dt.Rows.InsertAt直接修改了集合,触发了这个检查。
以下是两种可行的解决方法:
方法1:反向for循环遍历
使用for循环从最后一行往前遍历,插入新行不会影响未遍历的行索引,同时避开枚举器的集合修改限制:
void connecttosql() { dataGridView1.DataSource = null; dataGridView1.Rows.Clear(); SqlConnection cn = new SqlConnection(); SqlCommand cmd = new SqlCommand(); cn.ConnectionString = @"Data Source=(LocalDB)\MSSQLLocalDB;Integrated Security=True"; cmd.Connection = cn; cmd.Connection.Open(); cmd.CommandText = $"SELECT lot,item,toleranceMin,toleranceNom,toleranceMax,concernepar,donnees{comboBox1.Text+comboBox2.Text},{comboBox1.Text+comboBox2.Text} FROM Tolerance where {comboBox1.Text+comboBox2.Text} != ''"; SqlDataAdapter da = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); da.Fill(dt); DataColumn col = dt.Columns[$"donnees{comboBox1.Text + comboBox2.Text}"]; // 反向遍历行集合 for (int i = dt.Rows.Count - 1; i >= 0; i--) { DataRow row = dt.Rows[i]; string a = row[col].ToString(); // 安全转换整数,避免格式异常 if (int.TryParse(a, out int value) && value > 3) { DataRow row1 = dt.NewRow(); // 插入到当前行的下一个位置 dt.Rows.InsertAt(row1, i + 1); } } BindingSource source = new BindingSource(); source.DataSource = dt; dataGridView1.DataSource = source; }
方法2:先记录插入位置,再批量插入
先遍历一次DataTable,把所有需要插入行的位置存起来,再倒序批量插入(倒序是为了避免前面的插入操作导致后续位置偏移):
void connecttosql() { dataGridView1.DataSource = null; dataGridView1.Rows.Clear(); SqlConnection cn = new SqlConnection(); SqlCommand cmd = new SqlCommand(); cn.ConnectionString = @"Data Source=(LocalDB)\MSSQLLocalDB;Integrated Security=True"; cmd.Connection = cn; cmd.Connection.Open(); cmd.CommandText = $"SELECT lot,item,toleranceMin,toleranceNom,toleranceMax,concernepar,donnees{comboBox1.Text+comboBox2.Text},{comboBox1.Text+comboBox2.Text} FROM Tolerance where {comboBox1.Text+comboBox2.Text} != ''"; SqlDataAdapter da = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); da.Fill(dt); List<int> insertPositions = new List<int>(); DataColumn col = dt.Columns[$"donnees{comboBox1.Text + comboBox2.Text}"]; // 第一次遍历,记录所有需要插入的位置 for (int i = 0; i < dt.Rows.Count; i++) { DataRow row = dt.Rows[i]; string a = row[col].ToString(); if (int.TryParse(a, out int value) && value > 3) { insertPositions.Add(i + 1); } } // 倒序插入,避免位置偏移 foreach (int pos in insertPositions.OrderByDescending(p => p)) { DataRow row1 = dt.NewRow(); dt.Rows.InsertAt(row1, pos); } BindingSource source = new BindingSource(); source.DataSource = dt; dataGridView1.DataSource = source; }
额外优化建议
- 替换
int.Parse为int.TryParse:避免当a不是有效整数字符串时抛出格式异常,提升代码健壮性。 - 保留
BindingSource的使用:用它作为DataGridView的数据源,后续数据变更时能自动同步UI,比直接绑定DataTable更灵活。
内容的提问来源于stack exchange,提问作者LiterallyGutsFromBerserk
相关产品推荐
相关产品推荐

