You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过DataReader将选中字段数据添加到DataGridView?解决行归属报错

问题分析与解决方案

嘿,我来帮你排查这个问题!你遇到的Row provided already belongs to a DataGridView control错误,根源其实很简单:你在循环外只创建了一个DataGridViewRow实例,第一次插入后它已经属于DataGridView了,第二次循环再插入同一个对象就触发了控件的限制。

具体问题点

看你的代码,DataGridViewRow row = (DataGridViewRow)obj.Rows[0].Clone();这行是在while (dr.Read())循环外面定义的,意味着整个循环里你一直在复用同一个row对象。当你第一次调用obj.Rows.Insert(ri,row)后,这个row就被绑定到了DataGridView上,第二次再尝试插入它,控件自然会报错——一个行实例不能同时属于同一个DataGridView多次。

修改后的代码

把row的创建移到while循环内部,每次循环都克隆一个新的行对象,这样每次插入的都是独立的行,就不会有重复归属的问题了。另外我还优化了一些冗余代码和潜在的小问题:

public static void fillGrd(ref DataGridView obj, string tbl, string fld = "*", string cond = "")
{
    try
    {
        // 先清空原有数据
        obj.Rows.Clear();
        obj.Columns.Clear(); // 如果DataGridView已预先定义列,可删除此行

        // 拼接SQL语句
        cond = string.IsNullOrEmpty(cond) ? "" : " where " + cond;
        string qry = $"select {fld} from {tbl}{cond}";
        
        cmd.CommandText = qry;
        using (var dr = cmd.ExecuteReader()) // 使用using自动释放DataReader资源
        {
            if (dr.HasRows)
            {
                // 动态生成DataGridView列(按需保留)
                for (int i = 0; i < dr.FieldCount; i++)
                {
                    obj.Columns.Add(dr.GetName(i), dr.GetName(i));
                }

                int ri = 0;
                while (dr.Read())
                {
                    // 每次循环都克隆新的行
                    DataGridViewRow row = (DataGridViewRow)obj.Rows[0].Clone();
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        // 用GetValue避免类型转换问题,兼容非字符串字段
                        row.Cells[i].Value = dr.GetValue(i)?.ToString() ?? "";
                    }
                    obj.Rows.Insert(ri, row);
                    ri++;
                }
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Error occured! {ex.Message}");
    }
}

额外注意事项

  • 用using包裹DataReader,能自动关闭并释放资源,避免数据库连接泄漏;
  • 原来的dr.FieldCount -1会漏掉最后一列,改成dr.FieldCount才能读取所有字段;
  • 用dr.GetValue(i)?.ToString()替代dr.GetString(i),避免非字符串类型字段触发转换错误;
  • 如果你的DataGridView已经预先配置好列,可以删除动态生成列的代码块。

内容的提问来源于stack exchange,提问作者Deepal Nanayakkara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:03:52