Start Debugging

Dapper 2.1.86 возвращает DateOnly и TimeOnly спустя два года после их удаления

Dapper 2.1.86 снова включает встроенное сопоставление DateOnly и TimeOnly для параметров, членов и скалярных значений, с исправленными ошибками смещения столбца и тихого default(T). Что изменилось, что я измерил и что это значит для ваших собственных обработчиков типов.

Dapper 2.1.86 появился в NuGet 2026-09-12, и главный пункт в нём занимает одну строку в примечаниях к выпуску: “Re-enable DateOnly/TimeOnly support, fixing the defects that got it disabled”. Если вы со времён .NET 6 таскаете за собой SqlMapper.TypeHandler<DateOnly>, этот выпуск позволяет его удалить.

Как поддержка DateOnly появилась, сломалась и исчезла

Нативное сопоставление DateOnly/TimeOnly впервые появилось в 2.1.37 через #2051 в марте 2024 года. Уже через несколько недель пользователи 2.1.44 столкнулись с #2072: столбец datetime, сопоставленный со свойством DateOnly, падал с Error parsing column 1 (FromDate=Ed - String). Это выглядело как ошибка на единицу, потому что сообщение показывало значение не того столбца. В апреле 2024 года возможность исключили из компиляции (#2080), и все выпуски с 2.1.66 по 2.1.79 выходили без неё.

PR #2228 устраняет первопричины, а не симптомы:

До и после: замеры

Я запустил одно и то же файловое приложение на 2.1.79 и 2.1.86 с .NET SDK 10.0.302 и Microsoft.Data.Sqlite 10.0.12:

#:package Dapper@2.1.86
#:package Microsoft.Data.Sqlite@10.0.12
#:property PublishAot=false
using Dapper;
using Microsoft.Data.Sqlite;

using var c = new SqliteConnection("Data Source=:memory:");
c.Open();

c.ExecuteScalar<string>("select @d", new { d = new DateOnly(2026, 9, 14) });
c.ExecuteScalar<string>("select @t", new { t = new TimeOnly(9, 30) });
c.QuerySingle<DateOnly>("select '2026-09-14'");
c.QuerySingle<Row>("select 'x' as Name, '2026-09-14' as Due");

public class Row { public string Name { get; set; } = ""; public DateOnly Due { get; set; } }
Вызов2.1.792.1.86
Параметр DateOnlyNotSupportedException: cannot be used as a parameter value2026-09-14
Параметр TimeOnlyNotSupportedException09:30:00
QuerySingle<DateOnly>0001-01-01, без ошибки2026-09-14
Член DateOnlyDataException: Error parsing column 12026-09-14

Если вы всё ещё на старой версии, беспокоиться стоит именно о строке со скалярным значением: неверные данные и никакого исключения.

Что происходит с вашим существующим обработчиком типа

Стандартным обходным путём был SqlMapper.TypeHandler<DateOnly>, регистрируемый при запуске. С тем же обработчиком на 2.1.86 мой тест показал, что встроенное сопоставление берёт на себя параметры и члены DateOnly: методы обработчика SetValue и Parse ни разу не вызывались. Только скалярный путь QuerySingle<DateOnly> по-прежнему вызывал Parse. На 2.1.79 тот же обработчик срабатывал на всех трёх путях.

Если ваш обработчик только преобразовывал между DateOnly и DateTime, вы ничего не теряете. Если он делал что-то своё, например записывал даты как строки yyyyMMdd или целые числа, то теперь на пути параметров он пропускается, и база данных получает то, что провайдер делает с сырым DateOnly. Протестируйте перед обновлением.

Область действия

Поддержка скомпилирована для целевых платформ net8.0 и net10.0 в пакете. В сборках netstandard2.0 и net461 её нет, а набор тестов явно не ожидает, что она будет работать с устаревшим System.Data.SqlClient. Используйте Microsoft.Data.SqlClient.

Этот же выпуск также выводит из обращения фиды MyGet и AppVeyor: теперь Dapper публикуется только на nuget.org через Trusted Publishing (OIDC). Если nuget.config всё ещё указывает на старый фид MyGet для предварительных сборок, удалите его.

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Назад