EF6中一个关于时间类型 datetime2 的坑
在一个访问下位机的程序中,返回的时间戳有时候因断线产生0001年01月01日的时间,而原先使用拼接SQL进行数据存储的操作时,这个问题是可以跳过的。
这次把拼接SQL的部分重新改为EF进行管理,这个坑就不能避免了。
datetime2是个什么鬼?
datetime2 是一个在范围和精度上都优于 datetime 类型的时间类型。
传统的datetime类型,时间的最小值是 1753-01-01,精度最多到秒后三位。这也是被大家所熟知的时间类型。在今天的多数业务下,这个时间在使用上没有什么问题。
但是总有些不那么和谐的玩艺,居然总想搞个大新闻,用时间类型来标志异常(其实也没什么问题,毕竟异常了未必有时间戳,那么空的时间戳就出现了)
于是,时间的Null怎么表示呢?多数的策略选择了 0001-01-01 00:00:00这样一个时间。毕竟比起大家都知道的 1753-01-01,这个公元元年第一天的时间更具有标志意义。
但是传统那个Datetime它记不了这个值啊。
所以,一个更长、更细(好像哪里不对的样子)的datetime2类型出现了。 这个类型其实也基本被各个语言都实现了,所以算是一个标准。只是大多数程序员在很长的职业生涯里未必真的遇到这种情况,所以并不被多数人熟知。
那么,报错的实际情况是什么呢?
System.Data.SqlClient.SqlException: 从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值.
这个其实有点误导性质。
这个转换实质上是EF内部完成的。在EF创建了DB First的Model后,正常情况下,相关的这个映射字段的类型依然和数据库设计保持一致,是datetime。 但是,在赋值的过程中,如果这个字段没有赋值、或者赋值给出了0001-01-01的时间(或者小于1753的时间),结果就是EF会根据表的设计约束(显然就是字段必填了)转换成一个实质上的datetime2类型。(确实这个类型没办法自己声明出来啊,所以这应该算一个坑)
然后,接下来的故事就必然发生了,在EF执行 db.SaveChanges()操作时,数据库只接受datetime类型的日期,而不接受datetime2类型的值。进而就抛出这样一个错误。
so?解决方案呢?
显然,最直接的解决策略是改数据表的字段为 datetime2类型。 这个是支持的,所以没有什么大问题。当然后果就是,如果进行一个按时间正序进行的查询,那么肯定会有大量的0001-01-01的数据出现。在多数业务系统中,这种数据应该直接判定为错数而丢弃。
稍好的方案是对代码中的datetime设置为 Nullable 类型,允许空。 相比之下,这个做法更优雅一些,程序的逻辑更直观。
当然,也有一些算是奇淫技巧的方案,酌情吧:
- 在C#中用new DateTime(year,month,day,hour,minute,second)来限制精度
- 这个方法不太推荐,将model的edmx中的providerManifestToken设置成2005,这样ef就默认转化成datetime
个人觉得,这俩方案并不和谐。其一,需要在时间类型上作不少限制,其二,这样修改配置的思路基本上是只解决当前问题,不顾其他影响的思路。
在我的实际案例里,因为这个值需要作为标记异常的用途,所以在不修改前一个版本的底层的要求下,暂时给设置成1753-01-01确保兼容,在全新部署的版本上再进一步利用这个标志。
EF6中一个关于时间类型 datetime2 的坑的更多相关文章
- MySQL 中常见的时间类型有三种 DATE, DATETIME 和 TIMESTAMP
MySQL 中常见的时间类型有三种 DATE, DATETIME 和 TIMESTAMP,其中 DATE 类型用于表示日期,但是不会包含时间,格式为 YYYY-MM-DD,而 DATETIME 和 T ...
- PHPExcel对于Excel中日期和时间类型的处理
PHPExcel是一款优秀的处理Excel文件读写的开源PHP Library,能够给我们提供强大的Excel读写能力,本文针对Excel处理过程中关于日期和时间类型的处理进行深入的讨论.PHPExc ...
- MySQL 中的日期时间类型
日期时间类型中包含以下几种数据类型: DATE TIME DATETIME TIMESTAMP YEAR 各类型都有具体的取值范围,超出或非法的其他值时,MySQL 会回退到 0.TIMESTAMP ...
- MySQL中日期和时间类型
1 日期类型 MySql中关于日期的类型有Date/Datetime/Timestamp三种类型. 日期赋值时,允许"不严格"语法:任何标点符都可以用做日期部分或时间部分之间的间割 ...
- Ext如何Gird中如何显示时间类型的列?
rt,后台bean中的字段属性是Date类型,前台的model中的字段属性也设置为date类型,但是还是显示不出来,如何解决呢? 直接代码: grid中的COLUMN: Model中的定义:
- MySQL中日期与时间类型
http://blog.sina.com.cn/s/blog_4d8730df01014jiy.html
- oracle中两个时间类型的数据相减默认得到的是天数。
想要得到月份数,需要使用months_between函数. months_between(to_date('201707','yyyyMM'),to_date('201706','yyyyMM')) ...
- 「Flink」Flink中的时间类型
Flink中的时间类型和窗口是非常重要概念,是学习Flink必须要掌握的两个知识点. Flink中的时间类型 时间类型介绍 Flink流式处理中支持不同类型的时间.分为以下几种: 处理时间 Flink ...
- SQL Server的日期和时间类型
Sql Server使用 Date 表示日期,time表示时间,使用datetime和datetime2表示日期和时间. 1,秒的精度是指使用多少位小数表示秒 DateTime数据类型秒的精度是3,D ...
随机推荐
- SCUT - 483 - 数轴上的点
https://scut.online/p/483 改了题目之后发现,其实n个点放在[1,2N],要求间距至少是2,那么有且只有一个点和前面点的间距是3(设-1存在一个点),其他点的间距都必须是2.排 ...
- 关于jsp 获得当前绝对路径的方法
方法1) request.getRequestURL(); 方法2) request.getScheme()+"://"+request.getServerName()+&quo ...
- IPv6地址格式示例及IPv6与IPv4的区别分析
认识IPv6地址 IPv4地址是类似 A.B.C.D 的格式,它是32位,用\".\"分成四段,用10进制表示: 而IPv6地址类似X:X:X:X:X:X:X:X的格式,它是128 ...
- Tensorflow 2.0 学习资源
我从换了新工作才开始学习使用Tensorflow,感觉实在太难用了,sess和graph对 新手很不友好,各种API混乱不堪,这些在tf2.0都有了重大改变,2.0大量使用keras的 api,初步使 ...
- Codeforces 959 树构造 暴力求最小字典序互质序列
A B C 题目给你一个结论 最少需要min((odd,even)个结点可以把一棵树的全部边连起来 要求你输出两颗树 一棵树结论是正确的 另外一棵结论是正确的 正确结论的树很好造 主要是错误的树 题目 ...
- 面向对象原生js轮播图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Vscode窗口被覆盖
用Vscode用的好好的,突然就发现窗口被覆盖了 解决办法如下:1.ctrl+shift+p 快捷键打开如下界面, 2.接着在搜索框中输入settings,点击首先项:打开设置(json) 3.再se ...
- Pymongodb
首先安装pymongo模块 pip install pymongo 利用Python程序完成增删改查 import pymongo import json from bson import Objec ...
- unittest----skip(跳过用例)
我们在执行测试用例时,有时有些用例时不需要执行的,这时就需要用到unittest给我们提供的跳过用例的方法 @unittest.skip(reason):强制跳过,不需要判断条件.reason是跳过原 ...
- 【微信小程序】基础组件--view text image
组件的通用属性: id class style hidden bind* catch* data-* view 小程序基础组件,基本等于最常用组件,类似于HTML中的div.view用于构建页面骨架, ...