zoukankan      html  css  js  c++  java
  • 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 类型,允许空。 相比之下,这个做法更优雅一些,程序的逻辑更直观。

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

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

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

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

  • 相关阅读:
    VC 常见问题百问
    python windows 环境变量
    Check server headers and verify HTTP Status Codes
    Where are the AES 256bit cipher suites? Please someone help
    outlook 如何预订会议和会议室
    安装Axis2的eclipse插件后,未出现界面
    windows 环境变量
    python 时间日期处理汇集
    openldap学习笔记(使用openldap2.3.32)
    set p4 environment in windows
  • 原文地址:https://www.cnblogs.com/DannielZhang/p/7762885.html
Copyright © 2011-2022 走看看