SqlDataReader - GetStream против GetBytes для (n) varchar против v (n) varchar (max) или для xml / для json - PullRequest
0 голосов
/ 19 октября 2018

Я работал над способом предоставления доступа к крупным результатам SQL в виде потока, особенно когда запрос использует предложение for json или для xml.

Я заметил, что когда запрос возвращает json илиxml SqlDataReader не позволяет использовать метод GetStream(), который ожидается согласно документации:

'Недопустимая попытка GetStream для столбца' c '.Функция GetStream может использоваться только для столбцов типа Binary, Image, Udt или VarBinary. '

Однако, позволяет разрешать использование GetBytes().

Поведение является таким же, когда возвращаемые данные varchar(max) или nvarchar(max).GetStream() не будет работать, но GetBytes() будет работать.

С обычным ограниченным по длине столбцом varchar или nvarchar ни GetStream, ни GetBytes не допускаются.

Возможность вызова GetBytes означает, что я смог довольно легко создать пользовательский класс SqlTextStream : Stream, при условии, что при чтении из nvarchar, вероятно, лучше читать байты кратными двум, чтобы неРазбейте символы пополам.

Я просмотрел информацию, предоставленную SqlDataReader.GetColumnSchema(), но не нашел очевидной причины, по которой GetBytes допускается для n/varchar(max) результатов.Возможно, я что-то пропустил, но вывод GetColumnSchema кажется одинаковым для обычных или (макс.) Символьных данных, за исключением длины.

Кто-нибудь знает, почему GetBytes разрешено для n/varchar(max) столбцов?Как вы думаете, безопасно ли полагаться на то, что GetBytes разрешено?

Вот несколько простых тестовых кодов:

public void Test()
{
    var cmd1 = "select c = 'getbytes permitted here' for json path";
    var cmd2 = "select c = cast('getbytes also permitted here' as nvarchar(max))";
    var cmd3 = "select c = cast('getbytes not permitted here' as nvarchar(32))";

    using (var con = new SqlConnection("data source=theDB; initial catalog=playground; integrated security=SSPI"))
        // switch between cmd1, cmd2 and cmd3 to see the different behaviour.
        using (var cmd = new SqlCommand(cmd1, con))
        {
            con.Open();

            using (var rdr = cmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess))
            {
                var o = rdr.GetColumnSchema();
                var buffer = new byte[128];
                rdr.Read();
                //System.IO.Stream s = rdr.GetStream(0); this is never permitted
                rdr.GetBytes(0, 0, buffer, 0, buffer.Length); // this is permitted for cmd1 and cmd2
            }
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...