Found while probing #2226, but this one is independent of provider and Npgsql version — and it is silent, which makes it the more serious of the two.
With Dapper 2.1.72, a single-column query materialized as a bare DateOnly/TimeOnly returns the default value with no error:
| probe |
result |
QuerySingle<DateOnly>("select '2021-01-01'::date") (Npgsql 9 and 10) |
0001-01-01 ❌ silent |
QuerySingle<DateOnly>("select cast('2021-01-01' as date)") (SqlClient) |
0001-01-01 ❌ silent |
QuerySingle<TimeOnly>("select '03:03:03'::time") (Npgsql) |
00:00 ❌ silent |
ExecuteScalar<DateOnly>("select '2021-01-01'::date") (Npgsql) |
2021-01-01 ✅ |
POCO with a DateOnly member (Npgsql 10) |
2021-01-01 ✅ |
ExecuteScalar<DateOnly> and the member path are fine, so this looks like the Query<T> simple-vs-complex type decision not recognising DateOnly/TimeOnly as scalar types (Type.GetTypeCode reports Object for both) — the member-mapping deserializer then finds nothing to bind on a struct with no settable members and hands back a default instance. The type map entries added in #2051 (DoNotSetFieldValue/UseGetFieldValue) apparently don't reach this decision.
Wrong data with no exception is the worst failure mode available, so flagging it separately from #2226 rather than folding it in.
Found while probing #2226, but this one is independent of provider and Npgsql version — and it is silent, which makes it the more serious of the two.
With Dapper 2.1.72, a single-column query materialized as a bare
DateOnly/TimeOnlyreturns the default value with no error:QuerySingle<DateOnly>("select '2021-01-01'::date")(Npgsql 9 and 10)0001-01-01❌ silentQuerySingle<DateOnly>("select cast('2021-01-01' as date)")(SqlClient)0001-01-01❌ silentQuerySingle<TimeOnly>("select '03:03:03'::time")(Npgsql)00:00❌ silentExecuteScalar<DateOnly>("select '2021-01-01'::date")(Npgsql)2021-01-01✅DateOnlymember (Npgsql 10)2021-01-01✅ExecuteScalar<DateOnly>and the member path are fine, so this looks like theQuery<T>simple-vs-complex type decision not recognisingDateOnly/TimeOnlyas scalar types (Type.GetTypeCodereportsObjectfor both) — the member-mapping deserializer then finds nothing to bind on a struct with no settable members and hands back a default instance. The type map entries added in #2051 (DoNotSetFieldValue/UseGetFieldValue) apparently don't reach this decision.Wrong data with no exception is the worst failure mode available, so flagging it separately from #2226 rather than folding it in.