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

Npgsql+C#中DataReader未关闭报错,调用Close()无效求助

解决Npgsql + C#中“已存在打开的DataReader”错误

这个问题我之前处理过,本质是同一个数据库连接对象(conn)上同时存在两个未关闭的DataReader。虽然你手动调用了reader.Close(),但可能是因为手动关闭的时机不对,或者没有彻底释放DataReader占用的资源(Close()不一定会立即释放所有关联资源,Dispose()才能做到彻底清理)。下面给你几个可行的解决方案,优先推荐第一种:

方案1:使用using语句(最佳实践)

using语句是C#中管理资源的标准方式,它会在代码块结束时自动调用IDisposable.Dispose(),帮你彻底关闭DataReader并释放相关资源,完全避免手动管理的失误。修改你的代码如下:

IList<Borne> ListeBorne = new List<Borne>();

// 第一个查询:用using自动释放命令和阅读器
using (NpgsqlCommand maCommande2 = new NpgsqlCommand("Select * from borne;", conn))
using (NpgsqlDataReader monReader2 = maCommande2.ExecuteReader(CommandBehavior.CloseConnection))
{
    // 在这里读取monReader2的数据到ListeBorne
    while (monReader2.Read())
    {
        // 示例:根据你的Borne实体类调整读取逻辑
        ListeBorne.Add(new Borne
        {
            // 假设第一个字段是id,第二个是名称
            Id = monReader2.GetInt32(0),
            Libelle = monReader2.GetString(1)
        });
    }
} // 代码块结束时自动关闭monReader2和maCommande2

// 第一个阅读器已完全释放,现在执行第二个查询
using (NpgsqlCommand maCommandeEncaiss = new NpgsqlCommand("Select * from encaissement;", conn))
using (NpgsqlDataReader monReaderEncaiss = maCommandeEncaiss.ExecuteReader(CommandBehavior.CloseConnection))
{
    // 处理第二个阅读器的数据
    while (monReaderEncaiss.Read())
    {
        // 你的业务逻辑代码
    }
}

方案2:启用多活动结果集(MARS)

如果你确实需要在同一个连接上同时打开多个DataReader(比如嵌套查询场景),可以在数据库连接字符串中添加MultipleActiveResultSets=True配置:

Server=你的服务器地址;Port=5432;Database=你的数据库名;User Id=用户名;Password=密码;MultipleActiveResultSets=True;

注意:MARS虽然能解决同时打开多个阅读器的问题,但会带来额外的资源开销,非必要情况下不推荐使用,优先选择方案1。

方案3:手动确保阅读器彻底关闭

如果你坚持手动管理资源,一定要确保第一个DataReader完全关闭并释放后,再执行第二个查询:

IList<Borne> ListeBorne = new List<Borne>();
NpgsqlCommand maCommande2 = new NpgsqlCommand("Select * from borne;", conn);
NpgsqlDataReader monReader2 = maCommande2.ExecuteReader(CommandBehavior.CloseConnection);

// 读取第一个阅读器的数据
while (monReader2.Read())
{
    ListeBorne.Add(new Borne { /* 赋值逻辑 */ });
}

// 彻底关闭并释放第一个阅读器和命令
monReader2.Close();
monReader2.Dispose();
maCommande2.Dispose();

// 现在执行第二个查询
NpgsqlCommand maCommandeEncaiss= new NpgsqlCommand("Select * from encaissement;", conn);
NpgsqlDataReader monReaderEncaiss = maCommandeEncaiss.ExecuteReader(CommandBehavior.CloseConnection);

// 处理第二个阅读器数据
while (monReaderEncaiss.Read())
{
    // 你的逻辑
}

// 记得关闭第二个阅读器和命令
monReaderEncaiss.Close();
monReaderEncaiss.Dispose();
maCommandeEncaiss.Dispose();

总结一下:最稳妥、最符合C#规范的方式是使用using语句,它能帮你避免很多手动管理资源时容易犯的错误。

内容的提问来源于stack exchange,提问作者Chaima chouchou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:12:20