MySqlDataReader.GetStream() 抛出 IndexOutOfRangeException
MySqlDataReader.GetStream() throws IndexOutOfRangeException
所以我正在为我的 .NET Core 项目使用 MySql.Data 包,并将密码哈希和盐(byte[]
类型)作为 varbinary()
存储到数据库中。从用户那里选择密码散列和盐时,我需要一种方法将结果转换回字节数组。给定此示例代码
Stream passwordHashStream = dbDataReader.GetStream(0);
byte[] passwordHash;
using (MemoryStream memoryStream = new MemoryStream())
{
await passwordHashStream.CopyToAsync(memoryStream);
passwordHash = memoryStream.ToArray();
}
第一行会抛出这个异常
System.IndexOutOfRangeException: Data index must be a valid index in
the field at
MySql.Data.MySqlClient.Interceptors.ExceptionInterceptor.Throw(Exception
exception) at
MySql.Data.MySqlClient.MySqlConnection.Throw(Exception ex) at
MySql.Data.MySqlClient.MySqlDataReader.Throw(Exception ex) at
MySql.Data.MySqlClient.MySqlDataReader.GetBytes(Int32 i, Int64
fieldOffset, Byte[] buffer, Int32 bufferoffset, Int32 length) at
System.Data.Common.DbDataReader.GetStream(Int32 ordinal) at
Infrastructure.Persistence.Repositories.UsersRepository.<>c.<b__1_0>d.MoveNext()
in
/.../Infrastructure/Persistence/Repositories/UsersRepository.cs:line
60
尽管 reader 包含正确的数据库结果,如下所示(密码为 32 字节,哈希为 16 字节)
2018年报错
https://bugs.mysql.com/bug.php?id=93374
并且具有经过验证的状态。是否有任何好的解决方案/解决方法来解决它?我不想使用 GetBytes
方法,因为它要求我传入字节数组的长度,而我想独立于此。
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;
}
卸载 MySql.Data 并将其替换为 MySqlConnector。
(披露:我是 MySql bug you found and the primary contributor to MySqlConnector 的记者。)
除了修复该问题 and many other bugs,MySqlConnector 添加了真正的异步 I/O 支持和性能改进。
I don't want to use the GetBytes
method because it requires me to pass in the length of the byte array and I would like to stay independent from that.
如果您不想切换库,GetBytes
(MySql.Data 和 MySqlConnector 均支持)的一个鲜为人知的功能是传入一个 null
缓冲区 returns 所需的长度,因此您无需对其进行硬编码:
// 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);
所以我正在为我的 .NET Core 项目使用 MySql.Data 包,并将密码哈希和盐(byte[]
类型)作为 varbinary()
存储到数据库中。从用户那里选择密码散列和盐时,我需要一种方法将结果转换回字节数组。给定此示例代码
Stream passwordHashStream = dbDataReader.GetStream(0);
byte[] passwordHash;
using (MemoryStream memoryStream = new MemoryStream())
{
await passwordHashStream.CopyToAsync(memoryStream);
passwordHash = memoryStream.ToArray();
}
第一行会抛出这个异常
System.IndexOutOfRangeException: Data index must be a valid index in the field at MySql.Data.MySqlClient.Interceptors.ExceptionInterceptor.Throw(Exception exception) at MySql.Data.MySqlClient.MySqlConnection.Throw(Exception ex) at MySql.Data.MySqlClient.MySqlDataReader.Throw(Exception ex) at MySql.Data.MySqlClient.MySqlDataReader.GetBytes(Int32 i, Int64 fieldOffset, Byte[] buffer, Int32 bufferoffset, Int32 length) at System.Data.Common.DbDataReader.GetStream(Int32 ordinal) at Infrastructure.Persistence.Repositories.UsersRepository.<>c.<b__1_0>d.MoveNext() in /.../Infrastructure/Persistence/Repositories/UsersRepository.cs:line 60
尽管 reader 包含正确的数据库结果,如下所示(密码为 32 字节,哈希为 16 字节)
2018年报错
https://bugs.mysql.com/bug.php?id=93374
并且具有经过验证的状态。是否有任何好的解决方案/解决方法来解决它?我不想使用 GetBytes
方法,因为它要求我传入字节数组的长度,而我想独立于此。
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;
}
卸载 MySql.Data 并将其替换为 MySqlConnector。
(披露:我是 MySql bug you found and the primary contributor to MySqlConnector 的记者。)
除了修复该问题 and many other bugs,MySqlConnector 添加了真正的异步 I/O 支持和性能改进。
I don't want to use the
GetBytes
method because it requires me to pass in the length of the byte array and I would like to stay independent from that.
如果您不想切换库,GetBytes
(MySql.Data 和 MySqlConnector 均支持)的一个鲜为人知的功能是传入一个 null
缓冲区 returns 所需的长度,因此您无需对其进行硬编码:
// 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);