Skip to content

SqlSequentialTextReader ReadAsync returns 0 before the end of a file #3361

@m0a0k0s

Description

@m0a0k0s

Description

SqlSequentialTextReader ReadAsync returns 0 before the end of a file is reached when the number of characters requested varies.

It reproduces when the number of characters requested is different on each read. If reading with the same constant count of characters to read (e.g. 4096) it will always return slightly oversized buffer that will trigger a read on each iteration from SqlDataReader and everything will be fine.

In PrepareByteBuffer ArrayPool.Shared returns instance with 8192 size for requested byteBufferSize 4097 (4096 chars). _decoder. Convert returns 4096 bytesUsed so it's not an encoding issue.
The second iteration requests 1 chare less. It creates a buffer with 4096 length that is entirely in _leftOverBytes size limit. It skips the read from SqlDataReader here

if ((byteBufferUsed < byteBuffer.Length) || (byteBuffer.Length == 0))

and charsRead 0 at this time (unbuffered characters count read) returned as read bytes, which means the end of a file for the consumer.

To reproduce

	var reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken);
	var textReader = dataReader.DbDataReader.GetTextReader(0);
        
        var buffer = new char[4096];
        var result = -1;
        var start = 0;
        while (result != 0)
        {
            result = await textReader.ReadAsync(buffer, start, buffer.Length - start);
            start++;
        }

Expected behavior

A number of characters ready to process on current iteration returned even if it was buffered earlier.

Further technical details

Microsoft.Data.SqlClient version: 6.0.2
.NET target: .NET 9.0
SQL Server version: SQL Server 2022
Operating system: Windows 10

Metadata

Metadata

Labels

Triage Done ✔️Issues that are triaged by dev team and are in investigation.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions