public override int Read(byte[] buffer, int offset, int count) { CheckDisposed(); if (!CanRead) { throw new InvalidOperationException("Stream not open for reading"); } if (_isConsumed) { return(0); } if (_leftToReadInDataMsg == 0) { // We've consumed the current DataMessage (or haven't yet received the first), // read the next message var msg = _connector.ReadSingleMessage(); switch (msg.Code) { case BackendMessageCode.CopyData: _leftToReadInDataMsg = ((CopyDataMessage)msg).Length; break; case BackendMessageCode.CopyDone: _connector.ReadExpecting <CommandCompleteMessage>(); _connector.ReadExpecting <ReadyForQueryMessage>(); _isConsumed = true; return(0); default: throw _connector.UnexpectedMessageReceived(msg.Code); } } Contract.Assume(_leftToReadInDataMsg > 0); // If our buffer is empty, read in more. Otherwise return whatever is there, even if the // user asked for more (normal socket behavior) if (_buf.ReadBytesLeft == 0) { _buf.ReadMore(); } Contract.Assert(_buf.ReadBytesLeft > 0); var maxCount = Math.Min(_buf.ReadBytesLeft, _leftToReadInDataMsg); if (count > maxCount) { count = maxCount; } _leftToReadInDataMsg -= count; _buf.ReadBytes(buffer, offset, count); return(count); }