You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Dapper映射Postgres time到C# DateTime时的报错解决方法

解决Dapper映射PostgreSQL可空time字段到C#可空DateTime的问题

方法1:自定义Dapper类型处理器(TypeHandler)

通过实现Dapper的SqlMapper.TypeHandler<T>,可以全局统一处理PostgreSQL time字段到C# DateTime?的转换逻辑,无需在每个查询里手动处理。

首先创建自定义处理器:

public class PostgresTimeToNullableDateTimeHandler : SqlMapper.TypeHandler<DateTime?>
{
    public override DateTime? Parse(object value)
    {
        if (value == DBNull.Value)
            return null;

        // PostgreSQL的time类型在Npgsql驱动中会被解析为TimeSpan
        if (value is TimeSpan timeSpan)
            return new DateTime(1, 1, 1) + timeSpan; // 拼接默认日期

        throw new InvalidCastException($"无法将 {value.GetType().Name} 类型转换为 DateTime?");
    }

    public override void SetValue(IDbDataParameter parameter, DateTime? value)
    {
        if (!value.HasValue)
        {
            parameter.Value = DBNull.Value;
            return;
        }

        // 将DateTime的时间部分转换为TimeSpan存入数据库
        parameter.Value = value.Value.TimeOfDay;
        parameter.DbType = DbType.Time;
    }
}

然后在应用启动时注册这个处理器(比如Program.cs或Startup.cs):

SqlMapper.AddTypeHandler(new PostgresTimeToNullableDateTimeHandler());

注册后,Dapper会自动对所有DateTime?类型的属性应用这个转换逻辑,无需额外代码。

方法2:改用TimeSpan?类型接收(推荐)

PostgreSQL的time类型本质是时间跨度,Npgsql驱动默认会将其映射为C#的TimeSpan类型,而非DateTime。如果业务逻辑允许,直接将模型中的属性改为TimeSpan?,Dapper可以自动完成映射,完全不需要额外处理:

public class YourModel
{
    // 替换原来的DateTime? MyTimeField
    public TimeSpan? MyTimeField { get; set; }
}

这种方式更符合类型语义,避免了不必要的日期拼接,是最推荐的方案。

方法3:查询时SQL层面转换

如果只是个别查询需要处理,可以在SQL语句中将time字段转换为带默认日期的timestamp类型,让Dapper可以直接映射到DateTime?:

SELECT 
    other_fields,
    my_time_field::timestamp AS my_time_field  -- 将time转为timestamp
FROM your_table

PostgreSQL的::timestamp转换会自动给time字段拼接默认日期0001-01-01,和你手动拼接的逻辑一致,Dapper就能正常解析为DateTime?了。

内容的提问来源于stack exchange,提问作者lucky.expert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:15:52