ASP.NET MVC项目中,使用entity framework添加数据遇到“从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值”这个错误问题。后经过问题的排查,是由于C#代码中实体类所传入的DateTime类型属性没有赋值的原因,其中主要涉及到SQL Server 中datetime2的时间精度和日期范围的问题。
触发该错误的条件如下:
- SQL Server数据库版本中有datetime2类型
- 数据库中,某个要进行添加或者修改操作的字段的数据类型为datetime,比如表Table1中的InputDate字段,类型为datetime。
- 后台代码进行数据库操作时,传入的实体对象的DateTime类型的属性没有赋值,比如有一实体类Test,该类下有个InputDate属性,类型为DateTime。
- 最后使用entity framework对这个dateime类型的字段进行添加和修改操作就会出现此问题。
问题解析
一般之所以会报错数据类型转换产生一个超出范围的值,都是因为数据的大小和范围超出要转换的目标的原因。我们先看datetime2和datetime这两个数据类型的具体区别在哪里。
官方MSDN对于datetime2的说明:定义结合了 24 小时制时间的日期。 可将 datetime2 视作现有 datetime 类型的扩展,其数据范围更大,默认的小数精度更高,并具有可选的用户定义的精度。
这里值的注意的是datetime2的日期范围是"0001-01-01 到 9999-12-31"(公元元年 1 月 1 日到公元 9999 年 12 月 31 日)。而datetime的日期范围是:”1753 年 1 月 1 日到 9999 年 12 月 31 日“。这里的日期范围就是造成“从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值”这个错误的原因!!!
在c#中,如果实体类的属性没有赋值,一般都会取默认值,比如int类型的默认值为0,string类型默认值为null, 那DateTime的默认值呢?由于DateTime的默认值为"0001-01-01",所以entity framework在进行数据库操作的时候,在传入数据的时会自动将原本是datetime类型的数据字段转换为datetime2类型(因为0001-01-01这个时间超出了数据库中datetime的最小日期范围),然后在进行数据库操作。问题来了,虽然EF已经把要保存的数据自动转为了datetime2类型,但是数据库中表的字段还是datetime类型!所以将datetime2类型的数据添加到数据库中datetime类型的字段里去,就会报错并提示转换超出范围。
多种解决方案
这个问题的解决方法是很多的,关键是适合自己的业务逻辑和需求:
- C#代码中 DateTime类型的字段在作为参数传入到数据库前记得赋值,并且的日期要大于1753年1月1日。
- C#代码中 将原本是DateTime类型的字段修改为DateTime?类型,由于可空类型的默认值都是为null,所以传入数据库就可以不用赋值,数据库中的datetime类型也是支持null值的。
- 修改数据库中表的字段类型,将datetime类型修改为datetime2类型
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/98317.html