PostgreSQL-npgsql DataReader在读取循环期间断开连接并暂停

时间:2017-11-25 14:27:46

标签: .net postgresql npgsql

环境:postgres 9.6.3,npgsql 3.2.5,.net 4.5.1

我们执行导入/导出传输任务(大量数据逐行传输), 在读取期间使用游标和单独的连接来执行写入。

如果写操作需要一些时间(几秒钟),我们会在DataReader.Read()中收到以下错误:

Npgsql.NpgsqlException (0x80004005): Exception while reading from stream ---> System.IO.IOException: 
Unable to read data from the transport connection: 
An existing connection was forcibly closed by the remote host. ---> 
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at Npgsql.ReadBuffer.<Ensure>d__27.MoveNext()
   at Npgsql.ReadBuffer.<Ensure>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Npgsql.NpgsqlConnector.<DoReadMessage>d__148.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at Npgsql.NpgsqlConnector.<ReadMessage>d__147.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at Npgsql.NpgsqlDataReader.<Read>d__28.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Npgsql.NpgsqlDataReader.Read()

根据暂停的持续时间(3-4秒),我们可以获取:120,240,......记录,以及异常提升。    如果我们不暂停读取,并且我们在一个循环中读取所有数据,它就可以工作。

由于空间分配原因,我们无法读取内存中的所有数据。

我们看到收到的是:     在对DataReader.Read();

的失败调用期间发生DataReader_ReaderClosed事件

这是我们的PG功能骨架:

 CREATE FUNCTION "public"."myPGFunction" (INOUT cv_1 refcursor DEFAULT NULL::refcursor)  RETURNS refcursor
   AS $$

   begin  

      OPEN cv_1 FOR
        SELECT ....
        FROM .... a;

   end;
$$ LANGUAGE plpgsql

代码如下:

        _Connection = new NpgsqlConnection("");
        _Connection.Open();
        _Transaction = _Connection.BeginTransaction();
        _SelectCommand = _Connection.CreateCommand();

        _SelectCommand.CommandText = "myPGFunction";
        _SelectCommand.Connection = _Connection;
        _SelectCommand.CommandType = CommandType.StoredProcedure;

        NpgsqlParameter parCur = new NpgsqlParameter("cv_1".ToLower(), NpgsqlTypes.NpgsqlDbType.Refcursor);
        parCur.Direction = ParameterDirection.InputOutput;
        parCur.Value = "refcur";
        _SelectCommand.Parameters.Add(parCur);

        _SelectCommand.Transaction = _Transaction;
        _SelectCommand.ExecuteNonQuery();

        _SelectCommand.CommandText = "FETCH ALL IN \"refcur\"";
        _SelectCommand.CommandType = CommandType.Text;

        _DataReader = _SelectCommand.ExecuteReader();

这里是读取循环:

    while(_DataReader.Read())
    {
        // Read Data
        // Transfer data taking up to 3-4 seconds
        ...
    }

使用CommandText =&#34; FETCH ALL IN \&#34; refcur \&#34;&#34 ;;在ExecuteReader()之后执行_DataReader.Read()循环是否有任何超时; ?

顺便说一句,我们测试了几个Command Timeout值,甚至是特殊的&#34;内部命令超时&#34;或TCP保持活力等...    对我们的问题没有任何影响。

0 个答案:

没有答案