Npgsql奇怪的异常

3

这是手册中提供的例子。然而当我尝试相同操作时,却出现了很多异常。问题在哪里呢?

using(NpgsqlConnection conn = new NpgsqlConnection("connstring"))
{
    conn.Open();
    using(NpgsqlCommand command = new NpgsqlCommand("select command", conn))
    {
        command.Parameters.Add(new NpgsqlParameter("column1", NpgsqlDbType.Integer);
        command.Parameters[0].Value = 4;
        using(NpgsqlDataReader dr = command.ExecuteReader())
        {
            dr.Read();
            Console.Write("{0} \t", dr[0]);
        }
    }
}

异常:

System exception System.IO.IOException: I/O error occurred.
at Npgsql.NpgsqlState.<ProcessBackendResponses_Ver_3>d__a.MoveNext()
at Npgsql.NpgsqlState.IterateThroughAllResponses(IEnumerable`1 ienum)
at Npgsql.NpgsqlState.Query(NpgsqlConnector context, NpgsqlCommand command)
at Npgsql.NpgsqlConnector.Query(NpgsqlCommand queryCommand)
at Npgsql.NpgsqlConnector.ReleaseRegisteredListen()
at Npgsql.NpgsqlConnector.ReleaseResources()
at Npgsql.NpgsqlConnectorPool.UngetPooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
at Npgsql.NpgsqlConnectorPool.ReleasePooledConnectorInternal(NpgsqlConnection Connection, NpgsqlConnector Connector)
at Npgsql.NpgsqlConnectorPool.ReleasePooledConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
at Npgsql.NpgsqlConnectorPool.ReleaseConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
at Npgsql.NpgsqlConnection.Close()
at Npgsql.NpgsqlConnection.Dispose(Boolean disposing)
at System.ComponentModel.Component.Dispose()

现在这个功能可以正常工作了。那么它和之前有何不同呢?:
using(NpgsqlConnection conn = new NpgsqlConnection("connstring"))
{
    conn.Open();
    using(NpgsqlCommand command = new NpgsqlCommand("select command", conn))
    {
        command.Parameters.Add(new NpgsqlParameter("column1", NpgsqlDbType.Integer);
        command.Parameters[0].Value = 4;
        NpgsqlDataReader dr = command.ExecuteReader();            
        dr.Read();
        Console.Write("{0} \t", dr[0]);
    }
}

为什么DataReader不能与IDisposable一起使用?

在异常之前是否有任何结果,并且Postgres日志中是否有任何错误?NpgsqlState.IterateThroughAllResponses用于解析非结果查询的响应,当连接被清理时会发送内部查询。我认为这里可能是Npgsql存在缺陷,或者您的代码存在缺陷(也许是连接字符串或查询,在您的示例代码中没有给出),然后Npgsql处理不当,从其内部发出消息而不是对问题的良好解释。 - Jon Hanna
1
此外,您能否展示一下实际的 "connstring""select command",只需将用户名、服务器名和密码更改为 XXXX 即可。显然您不想公开这些信息,但问题可能就出在这里。 - Jon Hanna
1
这似乎是Npgsql中的一个问题,它没有正确处理错误情况。奇怪的是,为什么在释放连接时会出现IOExceptions。你在运行程序时断开了与服务器的连接吗? - Francisco Junior
connstring = "Server=127.0.0.1;Port=6001;User Id=test_test;Password=xxxxx;database=db_test"查询语句为"select column1 from table1 where id = xvalue",有时我会使用存储过程,"select value1,value2 from schema.function(:xvalue,:yvalue)",然后添加参数。问题是为什么不释放资源时它能够工作,而使用(NpgsqlDataReader dr = command.ExecuteReader())却不能。这是一个值得担忧的原因! - King
@FranciscoJunior 在 NPGSQL 手册中有一个程序,就像我的程序一样。这可能会出现什么问题? - King
显示剩余13条评论
1个回答

3
Npgsql在使用数据读取器和IDisposable时无法处理连接中断。如果服务器在与应用程序通信之前终止连接,并且当连接返回到连接池时,它会去服务器检查连接,此时数据读取器无法正确释放。在多线程环境中,这将出现不幸的情况。如果服务器从连接中断开自身,则不应立即终止,以使Npgsql无法向其回传信息。增加服务器的断开时间以更高的值。我的情况是强制突然断开服务器的连接。
解决方案:Npgsql应该内部处理异常,但目前尚未实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接