在一个访问下位机的程序中,返回的时间戳有时候因断线产生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 类型,允许空。 相比之下,这个做法更优雅一些,程序的逻辑更直观。

当然,也有一些算是奇淫技巧的方案,酌情吧:

  1. 在C#中用new DateTime(year,month,day,hour,minute,second)来限制精度
  2. 这个方法不太推荐,将model的edmx中的providerManifestToken设置成2005,这样ef就默认转化成datetime

个人觉得,这俩方案并不和谐。其一,需要在时间类型上作不少限制,其二,这样修改配置的思路基本上是只解决当前问题,不顾其他影响的思路。

在我的实际案例里,因为这个值需要作为标记异常的用途,所以在不修改前一个版本的底层的要求下,暂时给设置成1753-01-01确保兼容,在全新部署的版本上再进一步利用这个标志。

EF6中一个关于时间类型 datetime2 的坑的更多相关文章

  1. MySQL 中常见的时间类型有三种 DATE, DATETIME 和 TIMESTAMP

    MySQL 中常见的时间类型有三种 DATE, DATETIME 和 TIMESTAMP,其中 DATE 类型用于表示日期,但是不会包含时间,格式为 YYYY-MM-DD,而 DATETIME 和 T ...

  2. PHPExcel对于Excel中日期和时间类型的处理

    PHPExcel是一款优秀的处理Excel文件读写的开源PHP Library,能够给我们提供强大的Excel读写能力,本文针对Excel处理过程中关于日期和时间类型的处理进行深入的讨论.PHPExc ...

  3. MySQL 中的日期时间类型

    日期时间类型中包含以下几种数据类型: DATE TIME DATETIME TIMESTAMP YEAR 各类型都有具体的取值范围,超出或非法的其他值时,MySQL 会回退到 0.TIMESTAMP ...

  4. MySQL中日期和时间类型

    1 日期类型 MySql中关于日期的类型有Date/Datetime/Timestamp三种类型. 日期赋值时,允许"不严格"语法:任何标点符都可以用做日期部分或时间部分之间的间割 ...

  5. Ext如何Gird中如何显示时间类型的列?

         rt,后台bean中的字段属性是Date类型,前台的model中的字段属性也设置为date类型,但是还是显示不出来,如何解决呢? 直接代码: grid中的COLUMN: Model中的定义:

  6. MySQL中日期与时间类型

    http://blog.sina.com.cn/s/blog_4d8730df01014jiy.html

  7. oracle中两个时间类型的数据相减默认得到的是天数。

    想要得到月份数,需要使用months_between函数. months_between(to_date('201707','yyyyMM'),to_date('201706','yyyyMM'))  ...

  8. 「Flink」Flink中的时间类型

    Flink中的时间类型和窗口是非常重要概念,是学习Flink必须要掌握的两个知识点. Flink中的时间类型 时间类型介绍 Flink流式处理中支持不同类型的时间.分为以下几种: 处理时间 Flink ...

  9. SQL Server的日期和时间类型

    Sql Server使用 Date 表示日期,time表示时间,使用datetime和datetime2表示日期和时间. 1,秒的精度是指使用多少位小数表示秒 DateTime数据类型秒的精度是3,D ...

随机推荐

  1. SCUT - 483 - 数轴上的点

    https://scut.online/p/483 改了题目之后发现,其实n个点放在[1,2N],要求间距至少是2,那么有且只有一个点和前面点的间距是3(设-1存在一个点),其他点的间距都必须是2.排 ...

  2. 关于jsp 获得当前绝对路径的方法

    方法1) request.getRequestURL(); 方法2)  request.getScheme()+"://"+request.getServerName()+&quo ...

  3. IPv6地址格式示例及IPv6与IPv4的区别分析

    认识IPv6地址 IPv4地址是类似 A.B.C.D 的格式,它是32位,用\".\"分成四段,用10进制表示: 而IPv6地址类似X:X:X:X:X:X:X:X的格式,它是128 ...

  4. Tensorflow 2.0 学习资源

    我从换了新工作才开始学习使用Tensorflow,感觉实在太难用了,sess和graph对 新手很不友好,各种API混乱不堪,这些在tf2.0都有了重大改变,2.0大量使用keras的 api,初步使 ...

  5. Codeforces 959 树构造 暴力求最小字典序互质序列

    A B C 题目给你一个结论 最少需要min((odd,even)个结点可以把一棵树的全部边连起来 要求你输出两颗树 一棵树结论是正确的 另外一棵结论是正确的 正确结论的树很好造 主要是错误的树 题目 ...

  6. 面向对象原生js轮播图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. Vscode窗口被覆盖

    用Vscode用的好好的,突然就发现窗口被覆盖了 解决办法如下:1.ctrl+shift+p 快捷键打开如下界面, 2.接着在搜索框中输入settings,点击首先项:打开设置(json) 3.再se ...

  8. Pymongodb

    首先安装pymongo模块 pip install pymongo 利用Python程序完成增删改查 import pymongo import json from bson import Objec ...

  9. unittest----skip(跳过用例)

    我们在执行测试用例时,有时有些用例时不需要执行的,这时就需要用到unittest给我们提供的跳过用例的方法 @unittest.skip(reason):强制跳过,不需要判断条件.reason是跳过原 ...

  10. 【微信小程序】基础组件--view text image

    组件的通用属性: id class style hidden bind* catch* data-* view 小程序基础组件,基本等于最常用组件,类似于HTML中的div.view用于构建页面骨架, ...