diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 8f3956cab..4ee8c0587 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -3851,13 +3851,17 @@ private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int ind { TypeCode dataTypeCode = Type.GetTypeCode(colType), unboxTypeCode = Type.GetTypeCode(unboxType); bool hasTypeHandler; + bool providerValueIsAssignable = unboxType.IsAssignableFrom(colType); // note the TypeCode tests are only meaningful for distinct codes: TypeCode.Object // matching TypeCode.Object says nothing (TimeSpan vs TimeOnly?, say), and a direct // unbox there throws; such pairs belong to the flexible-convert path below. A column // reported as plain *object* (sql_variant etc) keeps the direct unbox: the runtime // box is the only truth available there - if ((hasTypeHandler = typeHandlers.ContainsKey(unboxType)) || colType == unboxType - || colType == typeof(object) || unboxType == typeof(object) + if ((hasTypeHandler = typeHandlers.ContainsKey(unboxType)) + || colType == unboxType + || providerValueIsAssignable + || colType == typeof(object) + || unboxType == typeof(object) || (dataTypeCode == unboxTypeCode && dataTypeCode != TypeCode.Object) || (dataTypeCode == Type.GetTypeCode(nullUnderlyingType) && dataTypeCode != TypeCode.Object) || colType == nullUnderlyingType) diff --git a/tests/Dapper.Tests/Providers/PostgresqlTests.cs b/tests/Dapper.Tests/Providers/PostgresqlTests.cs index b9d60f389..77c229075 100644 --- a/tests/Dapper.Tests/Providers/PostgresqlTests.cs +++ b/tests/Dapper.Tests/Providers/PostgresqlTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Data; using System.Data.Common; using System.Linq; using Xunit; @@ -68,6 +67,30 @@ private class DateReadings public DateOnly AsDateOnly { get; set; } public DateTime? AsNullableDateTime { get; set; } } + + private sealed record NumericArraysTable + { + public IReadOnlyCollection Longs { get; set; } = []; + public IReadOnlyCollection Ints { get; set; } = []; + public IReadOnlyCollection Shorts { get; set; } = []; + } + + [FactPostgresql] + public void TestPostgresqlBigintArrayMapsToReadOnlyCollection() + { + using var conn = GetOpenNpgsqlConnection(); + + var row = conn.QuerySingle( + @"SELECT + ARRAY[1001, 1002, 1003]::bigint[] AS ""Longs"" + , ARRAY[2001, 2002, 2003]::int[] AS ""Ints"" + , ARRAY[3001, 3002, 3003]::smallint[] AS ""Shorts"" + ;"); + + Assert.Equal(new [] { 1001L, 1002L, 1003L }, row.Longs.ToArray()); + Assert.Equal(new [] { 2001, 2002, 2003 }, row.Ints.ToArray()); + Assert.Equal(new short[] { 3001, 3002, 3003 }, row.Shorts.ToArray()); + } #endif [FactPostgresql]