#2226·Dapper

DateOnly/DateTime coercion gaps on 'date' columns (breaks with Npgsql 10, and SqlClient the other way)

Author: mgravellCreated Aug 20, 2026Updated Aug 20, 2026

Sibling of DapperLib/DapperAOT#202 (fixed on the AOT side in DapperLib/DapperAOT#203); vanilla has the same gap, in both directions. Adjacent to but distinct from #2072.

Npgsql 10 changed reader.GetValue() for a date column to return DateOnly rather than DateTime. Probed against Dapper 2.1.72 with a date column holding 2021-01-01:

probe Npgsql 9.0.2 (DateTime box) Npgsql 10.0.2 (DateOnly box) SqlClient (DateTime box)
Query<DateTime> DataException (inner: DateOnly is not IConvertible)
Query<DateTime?> ❌ same
POCO DateTime member ❌ same
POCO DateOnly member DataException (DateTime box) ❌ same as Npgsql 9

So there is no DateOnlyDateTime coercion in either direction on the read path: providers that box DateTime break DateOnly members, and Npgsql 10 (boxing DateOnly) breaks DateTime members and typed scalars. Each provider/version combination has a working direction and a broken one, which makes upgrading Npgsql a breaking change for any model that reads dates as DateTime.

The AOT-side fix was simply to accept either box shape in the conversion helper, keyed on the runtime value — DateOnlyToDateTime(TimeOnly.MinValue) for a DateTime target, and the equivalent in reverse; the same treatment fits FlexibleConvert/the parse paths here.

Repro is a 30-line console app (fresh postgres:16 container + select '2021-01-01'::date); happy to PR the fix.