Skip to content

Commit

Permalink
Fix #524 - GridReader should use the same conversion code as the re…
Browse files Browse the repository at this point in the history
…gular reader
  • Loading branch information
mgravell committed May 27, 2016
1 parent c3beb60 commit c7ed6ec
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Dapper.Tests/Tests.QueryMultiple.cs
Expand Up @@ -141,7 +141,7 @@ public void Issue524_QueryMultiple_Cast()
{ // aka: Read<int> should work even if the data is a <long>

// using regular API
connection.Query<int>("select cast(42 as bigint)").IsEqualTo(42);
connection.Query<int>("select cast(42 as bigint)").Single().IsEqualTo(42);
connection.QuerySingle<int>("select cast(42 as bigint)").IsEqualTo(42);

// using multi-reader API
Expand Down
2 changes: 1 addition & 1 deletion Dapper/SqlMapper.GridReader.Async.cs
Expand Up @@ -181,7 +181,7 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
}
else
{
var result = ReadDeferred<T>(gridIndex, deserializer.Func, typedIdentity);
var result = ReadDeferred<T>(gridIndex, deserializer.Func, typedIdentity, type);
if (buffered) result = result.ToList(); // for the "not a DbDataReader" scenario
return Task.FromResult(result);
}
Expand Down
26 changes: 20 additions & 6 deletions Dapper/SqlMapper.GridReader.cs
Expand Up @@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;

using System.Globalization;
namespace Dapper
{
partial class SqlMapper
Expand Down Expand Up @@ -161,7 +161,7 @@ private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
cache.Deserializer = deserializer;
}
IsConsumed = true;
var result = ReadDeferred<T>(gridIndex, deserializer.Func, typedIdentity);
var result = ReadDeferred<T>(gridIndex, deserializer.Func, typedIdentity, type);
return buffered ? result.ToList() : result;
}

Expand All @@ -184,8 +184,16 @@ private T ReadRow<T>(Type type, Row row)
deserializer = new DeserializerState(hash, GetDeserializer(type, reader, 0, -1, false));
cache.Deserializer = deserializer;
}
result = (T) deserializer.Func(reader);
if ((row & Row.Single) != 0 && reader.Read()) ThrowMultipleRows(row); while (reader.Read()) { }
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 && reader.Read()) ThrowMultipleRows(row);
while (reader.Read()) { }
}
else if((row & Row.FirstOrDefault) == 0) // demanding a row, and don't have one
{
Expand Down Expand Up @@ -297,13 +305,19 @@ public IEnumerable<TReturn> Read<TReturn>(Type[] types, Func<object[], TReturn>
return buffered ? result.ToList() : result;
}

private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> deserializer, Identity typedIdentity)
private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> deserializer, Identity typedIdentity, Type effectiveType)
{
try
{
var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
while (index == gridIndex && reader.Read())
{
yield return (T)deserializer(reader);
object val = deserializer(reader);
if (val == null || val is T) {
yield return (T)val;
} else {
yield return (T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture);
}
}
}
finally // finally so that First etc progresses things even when multiple rows
Expand Down

0 comments on commit c7ed6ec

Please sign in to comment.