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 ...
随机推荐
- B/S,C/S架构的区别
B/S架构:browser/server,采用的是浏览器服务器模式. C/S架构:client/server,采用的是客户端服务器模式. B/S架构,客户端是浏览器基本不需要维护,只需要维护升级服务器 ...
- JS 的 Array 和String 常混淆方法
知识一: 1.slice() 提取字符串 slice[ start, end) 如果参数为负数,表示从尾部开始算起. 2.subString() 提取字符串 3.subStr() 提取字符串 subS ...
- 已知链表头结点指针head,写一个函数把这个链表逆序
Node* ReverseList ( Node *head ) { if ( head == NULL || head->next == NULL ) return head; Node *p ...
- 工具使用——IDEA常用的几种插件
Rainbow Brackets:彩虹颜色的括号 Maven Helper :分析依赖冲突插件 Grep Console:显示不同日志级别不同颜色 Mybatis Log Plugin:直接将Myba ...
- linux常用的小命令
查看linux版本 uname -a 图上可知,linux内核版本为2.6.32 查看cpu核数 cat /proc/cpuinfo |grep "cores"| uniq 系统中 ...
- Kafka---系统学习
1.Topics 1.1.Topic 就是 数据主题: 1.2.作用:数据记录 发布的地方,用来 区分 业务系统: 1.3.每个Topic 可以有多个 消费者 订阅它的数据: 1.4.每个T ...
- 【牛客Wannafly挑战赛23】F 计数
题目链接 题意 给定一张边带权的无向图,求生成树的权值和是 k 的倍数的生成树个数模 p 的值. \(n\leq 100,k\leq 100,p\mod k=1\) Sol 看见整除然后 \(p\mo ...
- python-hasattr()、getattr()、setattr()函数的使用
python中hasattr().getattr().setattr()函数 class A(): name = 'python' def __init__(self): setattr(self._ ...
- unigui ios微信界面错位和点击失灵问题
IOS微信下会出现二个严重问题: 1.输入框失去焦点导致控件错位,造成无点正常点击. 此问题是微信自带浏览器,一直遗留问题, 尝试了多种方法始终无解.因此要用来开发公众号的一定要注意. 2.界面下移 ...
- 超赞的Linux软件分享(持续更新)
开发 Android studio - Android 的官方 IDE:Android Studio 提供在各种类型的安卓设备上构建应用最快的工具. Aptana - Aptana Studio 利用 ...