问题排查

在日常开发中,我们常用日期时间类型是 DateTime,该日期类型对应 Sql Server 中的 datetime2 类型。在排查过程中发现,数据库中日期字段使用的类型是 datetime 。原来是 datetime2转换为datetime 引发的 SqlDateTime overflow

datetime2 与 datetime 的区别

datetime2 对应 c# 中的 DateTime 类型。

Console.WriteLine(DateTime.MinValue);
Console.WriteLine(DateTime.MaxValue);
// MinValue: 01/01/0001 00:00:00
// MaxValue: 12/31/9999 23:59:59

datetime2 的取值范围是 01/01/0001 00:00:00 - 12/31/9999 23:59:59

datetime 的取值范围是 1/1/1753 12:00:00 AM - 12/31/9999 11:59:59 PM

解决

当我们查询的日期超出了datetime能表示范围的时候,就会引发 SqlDateTime overflow

这里有两种方案可以做参考:

  • 数据库中的日期类型修改为 datetime2
  • 在程序中实现一个扩展方法,在查询前检查日期是否会超过datetime 表示范围,手动设值。
public static class DateTimeExtension
    {
        public static DateTime ToSqlDateTime(this DateTime dateTime)
        {
            var sqlDateTimeMinValue = Convert.ToDateTime("1/1/1753 12:00:00 AM");
            var sqlDateTimeMaxValue = Convert.ToDateTime("12/31/9999 11:59:59 PM");

            if (dateTime < sqlDateTimeMinValue)
            {
                return sqlDateTimeMinValue;
            }

            if (dateTime > sqlDateTimeMaxValue)
            {
                return sqlDateTimeMaxValue;
            }

            return dateTime;
        }
    }

我比较推荐方案一的,改动比较少。方案二,需要给每一个可能引发异常的日期,添加检查,改动比较多。