MySqlDataReader.GetStream () выбрасывает исключение IndexOutOfRangeException - PullRequest
1 голос
/ 11 июля 2020

Итак, я использую пакет MySql .Data для моего. NET Core проекта и храню хэши и соли паролей (типа byte[]) как varbinary() в базе данных. При выборе пароля ha sh и соли от пользователя мне нужен способ преобразовать результат обратно в массив байтов. Учитывая этот пример кода

Stream passwordHashStream = dbDataReader.GetStream(0);
byte[] passwordHash;
                        
using (MemoryStream memoryStream = new MemoryStream())
{
    await passwordHashStream.CopyToAsync(memoryStream);
    passwordHash = memoryStream.ToArray();
}

, первая строка вызовет это исключение

System.IndexOutOfRangeException: индекс данных должен быть допустимым индексом в поле MySql .Data. MySqlClient.Interceptors.ExceptionInterceptor.Throw (исключение исключения) в MySql .Data.MySqlClient.MySqlConnection.Throw (Exception ex) в MySql .Data.MySqlClient.MySqlDataReader.Throw (Exception * .Data) в * 1028 MySqlClient.MySqlDataReader.GetBytes (Int32 i, Int64 fieldOffset, Byte [] buffer, Int32 bufferoffset, Int32 length) в System.Data.Common.DbDataReader.GetStream (порядковый номер Int32) в Infrastructure.Persistence.Repositories.UsersRepository29. <> * 10 *. d.MoveNext () в /.../Infrastructure/Persistence/Repositories/UsersRepository.cs:line 60

, хотя считыватель содержит правильные результаты базы данных, как вы можете видеть здесь ниже (пароль 32 байта, ha sh равно 16 байтам)

enter image description here

The error was reported in 2018

https://bugs.mysql.com/bug.php?id=93374

и имеет проверенный статус. Есть ли хорошие решения / обходные пути, как решить эту проблему? Я не хочу использовать метод GetBytes, потому что он требует, чтобы я передавал длину массива байтов, и я хотел бы оставаться независимым от этого.

Ответы [ 2 ]

1 голос
/ 11 июля 2020

Удалите MySql .Data и замените его на MySqlConnector .

(Раскрытие: я сообщаю об ошибке MySql, обнаруженной вами и основной участник MySqlConnector .)

Помимо исправления этой проблемы и многих других ошибок , MySqlConnector добавляет истинную поддержку asyn c ввода-вывода и улучшения производительности .

Я не хочу использовать метод GetBytes, потому что он требует, чтобы я передавал длину массива байтов, и я хотел бы оставаться независимым от этого.

Если вы не хотите переключать библиотеки, малоизвестная функция GetBytes (поддерживаемая как MySql .Data, так и MySqlConnector) заключается в том, что передача в буфере null возвращает необходимую длину, поэтому вам не нужно его жестко кодировать:

// get the length of the column and allocate a buffer
var length = dbDataReader.GetBytes(0, 0, null, 0, 0);
var passwordHash = new byte[length];

// fill the buffer from the column
dbDataReader.GetBytes(0, 0, passwordHash, 0, passwordHash.Length);
0 голосов
/ 11 июля 2020

public static async Task<MemoryStream> ToMemoryStream(this Stream stream)
    {
      var memStream = stream as MemoryStream;
      if (memStream == null)
      {
        memStream = new MemoryStream();
        await stream.CopyToAsync(memStream);
      }
      return memStream;
    }
...