Dapper 默认不支持
TimeSpan类型的直接映射,尤其在使用 SQLite 或某些数据库提供程序时(如 Microsoft.Data.Sqlite),
TimeSpan会被明确排除在自动转换列表之外。
为什么 Dapper 不原生映射 TimeSpan
SQL Server 的
time类型逻辑上对应 .NET 的
TimeSpan,但 Dapper 的内置类型处理器只覆盖常见基础类型(
int、
string、
DateTime等),而未包含
TimeSpan。官方文档与源码注释中已明确说明:它不能处理 TimeSpan、DateTimeOffset、Guid 等类型,需手动注册处理器。
SQL Server 中 time → TimeSpan 的正确映射方式
在 SQL Server 场景下,可借助自定义
ITypeHandler<timespan></timespan>实现双向转换: 写入时:将
TimeSpan转为
TimeSpan.ToString("g") 或直接传给 SqlParameter并设
SqlDbType.Time读取时:从
SqlDataReader.GetTimeSpan()或
GetValue()后解析字符串/TimeSpan 注册处理器:调用
SqlMapper.AddTypeHandler(typeof(TimeSpan), new TimeSpanHandler())
SQLite 等轻量数据库的替代方案
SQLite 没有原生
time类型,通常用
TEXT(如 "14:30:00")或
INTEGER(秒数)存储时间跨度。此时建议: 读取时用
ParseExact或
TimeSpan.FromSeconds手动转换 避免依赖自动映射,改用
DynamicParameters显式控制参数类型 若频繁使用,封装一个轻量
TimeSpanHandler并全局注册
实用小技巧:不用自定义处理器也能临时处理
对简单场景,可绕过映射限制:
查询时用Query<dynamic></dynamic>或匿名类型,再手动转
TimeSpan插入时把
TimeSpan.TotalSeconds当
int存,读取后再构造
TimeSpan用
DateOnly/
TimeOnly(.NET 6+)替代部分
TimeSpan语义,Dapper 支持更好
基本上就这些。关键不是“能不能”,而是“要不要自己搭桥”——Dapper 把控制权留给你,也正因如此,它轻、快、不越界。
