ReadAsync normalization

This does proper type conversion like other paths so everything aligns. Fix for #1496 and #1648.

We should follow-up here with an aggressively inlined shared approach, but getting everything normalized first. Added tests that fail against current code here.
This commit is contained in:
Nick Craver
2021-05-09 18:50:50 -04:00
parent dffb443e01
commit 2e753abc1c
3 changed files with 41 additions and 2 deletions
+21 -2
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -210,7 +211,16 @@ namespace Dapper
deserializer = new DeserializerState(hash, GetDeserializer(type, reader, 0, -1, false));
cache.Deserializer = deserializer;
}
result = (T)deserializer.Func(reader);
object val = deserializer.Func(reader);
if (val == null || val is T)
{
result = (T)val;
}
else
{
var convertToType = Nullable.GetUnderlyingType(type) ?? type;
result = (T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture);
}
if ((row & Row.Single) != 0 && await reader.ReadAsync(cancel).ConfigureAwait(false)) ThrowMultipleRows(row);
while (await reader.ReadAsync(cancel).ConfigureAwait(false)) { /* ignore subsequent rows */ }
}
@@ -230,7 +240,16 @@ namespace Dapper
var buffer = new List<T>();
while (index == gridIndex && await reader.ReadAsync(cancel).ConfigureAwait(false))
{
buffer.Add((T)deserializer(reader));
object val = deserializer(reader);
if (val == null || val is T)
{
buffer.Add((T)val);
}
else
{
var convertToType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
buffer.Add((T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture));
}
}
return buffer;
}
+10
View File
@@ -240,6 +240,16 @@ namespace Dapper.Tests
}
}
[Fact]
public async Task TestMultiConversionAsync()
{
using (SqlMapper.GridReader multi = await connection.QueryMultipleAsync("select Cast(1 as BigInt) Col1; select Cast(2 as BigInt) Col2").ConfigureAwait(false))
{
Assert.Equal(1, multi.ReadAsync<int>().Result.Single());
Assert.Equal(2, multi.ReadAsync<int>().Result.Single());
}
}
[Fact]
public async Task TestMultiAsyncViaFirstOrDefault()
{
+10
View File
@@ -31,6 +31,16 @@ namespace Dapper.Tests
}
}
[Fact]
public void TestMultiConversion()
{
using (SqlMapper.GridReader multi = connection.QueryMultiple("select Cast(1 as BigInt) Col1; select Cast(2 as BigInt) Col2"))
{
Assert.Equal(1, multi.Read<int>().Single());
Assert.Equal(2, multi.Read<int>().Single());
}
}
[Fact]
public void TestQueryMultipleNonBufferedIncorrectOrder()
{