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

点击DataGridView单元格读取数据到TextBox时出现读取器已关闭错误

解决「Invalid attempt to call Read when reader is closed」错误

我来帮你搞定这个问题!这个错误的核心原因是你的SqlDataReader在尝试读取数据之前就被意外关闭了,再加上代码里还有几个容易引发问题的细节,咱们一步步来修正:

问题分析

  1. 全局资源未正确管理:你使用了全局的SqlCommand和SqlConnection对象,这类对象如果被重复使用且没有正确清理状态,很容易出现连接/读取器状态异常的情况。
  2. 缺少资源自动释放机制:没有用using语句包裹数据库相关对象,它们的生命周期无法被自动管理,可能导致连接泄漏或者读取器被提前关闭。
  3. SQL注入风险:直接把dataGridView的单元格值拼接到SQL语句里,这是非常危险的操作,容易被恶意利用。
  4. 未处理边界情况:没有判断dataGridView2是否有选中行,直接访问SelectedRows[0]会引发索引越界异常。

修复后的代码

private void dataGridView2_CellClick(object sender, DataGridViewCellEventArgs e)
{
    // 先判断是否有选中的行
    if (dataGridView2.SelectedRows.Count == 0)
        return;

    // 获取选中行的id_subdiss值
    var subDissId = dataGridView2.SelectedRows[0].Cells[0].Value;
    if (subDissId == DBNull.Value || subDissId == null)
        return;

    // 使用using语句自动管理连接、命令、读取器的生命周期
    using (SqlConnection cn = new SqlConnection("你的数据库连接字符串"))
    using (SqlCommand cmd = new SqlCommand("select * from subdiseases where id_subdiss = @SubDissId", cn))
    {
        // 添加参数,避免SQL注入
        cmd.Parameters.AddWithValue("@SubDissId", subDissId);

        cn.Open();
        using (SqlDataReader dr4 = cmd.ExecuteReader())
        {
            // 读取数据前先判断是否有结果
            if (dr4.Read())
            {
                a = dr4["id_diss"].ToString();
                comboBox1.Text = dr4["name_diss"].ToString();
                namesub.Text = dr4["name_subdiss"].ToString();
                namedet.Text = dr4["details"].ToString();
            }
        } // 读取器会在这里自动关闭
    } // 命令和连接会在这里自动关闭
}

关键改进点

  • 使用using语句:确保SqlConnection、SqlCommand、SqlDataReader在使用完毕后自动释放资源,避免状态异常和资源泄漏。
  • 参数化查询:用@SubDissId参数代替直接拼接字符串,彻底消除SQL注入风险。
  • 边界情况处理:先检查是否有选中行、单元格值是否有效,避免不必要的异常。
  • 避免全局数据库对象:每次操作创建新的连接和命令对象,保证状态干净。

内容的提问来源于stack exchange,提问作者ah medo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:02:21