今天在用EF做插入操作的时候发现数据库中一个datetime类型的字段(CreateDate)的值居然全部为null。于是赶紧看表结构发现CreateDate字段居然是允许为空的。

虽然为空,但是设置了默认值getdate(),按说不应该为null的。于是开始测试。

字段允许Null值的情况

Users表结构如下:

假如一个字段有了默认值,并且又允许为Null,在做插入操作时会发生什么?

如上图中的表结构,CreateDate是允许为null的,而又有默认值getdate()。这样在用传统SQL语句和EF做插入操作时分别会发生什么呢?

先看传统SQL语句:

insert into Users(Username,Password) values('test','123456')

插入结果:

使用SQL完全没有问题。

再看使用EF:

Users user = new Users();
user.Username = "test2";
user.Password = "123456"; TestEntities entity = new TestEntities();
entity.Users.Add(user);
int result = entity.SaveChanges();

插入结果:

使用EF插入居然为NULL!!!于是立刻打开SQL Server Profiler监测生成的SQL,EF居然生成了下面的SQL:

没赋值的字段,EF生成SQL的时候居然都置为NULL,管你有没有设默认值!

可能是EF比较娇情,我字段允许为NULL,EF生成SQL时就置为null了。那我把字段设为不允许为NULL,EF又会生成怎样的SQL呢?

字段不允许Null值的情况

Users表结构如下:

这一次CreateDate不允许为NULL了,使用SQL理所当然地一切正常:

insert into Users(Username,Password) values('admin','123456')

那再看下用EF:

Users user = new Users();
user.Username = "admin";
user.Password = "123456"; TestEntities entity = new TestEntities();
entity.Users.Add(user);
int result = entity.SaveChanges();

结果。。。

”从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值。“

EF很傲娇地抛了个异常!!为什么会抛出这个异常?这个异常神马意思?于是照妖镜SQL Server Profiler又出场了:

日期类型的字段如果不赋值会给默认值“0001-01-01 00:00:00”,这和生成SQL无关,是在生成SQL之前CLR进行的初始化操作,同理String类型的字段如果不赋值会给默认值String.Empty!

但是,那也不至于抛异常啊,顶多字段值存储为“0001-01-01 00:00:00”呗。

于是查MSDN发现datetime类型的日期范围仅支持1750-01-01 00:00:00至9999-12-31 23:59:59.997,而0001-01-01 00:00:00不在此范围内,所以抛出异常。原来如此。

datetime和datetime2支持的日期范围如下:

结论

如此看来无论字段有没有默认值,使用EF插入时都没有任何实际作用了。因此如果你使用EF建议干脆直接写死算了。比如user.CreateDate = DateTime.Now。

ps.这里只是举个例子,事实上,在实际项目中不建议写成DateTime.Now,因为数据库系统时间和服务器时间一般是不同的,笔者实际项目中其实是封装了一个方法叫GetSQLServerSystemDateTime。

除此之外是否还有别的方法呢?

方法是有的,打开EF的.edmx文件,找到<EntityType Name="表名">节点,把如下节点:

<Property Name="CreateDate" Type="datetime" Nullable="false"  />

改成:

<Property Name="CreateDate" Type="datetime" Nullable="false" StoreGeneratedPattern="Computed" />

即可。

StoreGeneratedPattern是一个枚举:
  • None 一个值,指示它不是服务器生成的属性。这是默认值。如果没有StoreGeneratedPattern属性,其值就默认为None。
  • Identity 执行插入时生成一个值,但在执行更新时保持不变。
  • Computed 执行插入和更新时都将生成一个值。

笔者经过实际测试发现:

  1. 如果将StoreGeneratedPattern值设置为Identity,只要一修改CreateDate字段就会抛异常;
  2. 如果把StoreGeneratedPattern值设置为Computed不会抛异常,但值仍然没有被修改,即使你写了user.CreateDate = "xxx"。

所以如果你使用EF,我还是建议采用第一种方式,直接在程序中赋值user.CreateDate = xx.GetSQLServerSystemDateTime()。这种方法省事且安全。修改edmx文件太麻烦,况且每增加一个datetime类型的字段都要修改一次edmx文件。

最后感谢大家提出的建议,欢迎大家亲自测试并把结果反馈给我。

延伸阅读关于有默认值的字段在用EF做插入操作时的思考(续)

关于有默认值的字段在用EF做插入操作时的思考的更多相关文章

  1. 关于有默认值的字段在用EF做插入操作时的思考(续)

    问题描述 今天下午(看现在这时间,应该是昨天下午了哈),园友 choon 写了这样一篇博文<关于有默认值的字段在用EF做插入操作时的思考>. 博文内容主要记录的是 choon 使用 EF ...

  2. 在向"带有自增字段的数据库表"中插入数据时,自定义"该自增字段"的数据

    在设计数据库表的时候,经常会使用自增主键或其他自增字段.比如: DB_UserGroups表中GroupID为该表主键,并为自增字段. 但在将某字段设置自增后,想在插入数据时,人为指定自增字段的数据内 ...

  3. SQL ser 进行表中的插入操作时,变量字段名,导致报错时解决办法 :动态SQL

    标题不能描述的很清楚,下面具体说所我要描述的问题,和解决的办法. 作为SQL小白一枚,近日在写一段代码,代码如下: 报错显示 变量@vv附近错误. 后来经过了解,原来是因为,这样需要使用 动态SQL去 ...

  4. SQL语句增加字段、修改字段、修改类型、修改默认值

    一.修改字段默认值 alter table 表名 drop constraint 约束名字   ------说明:删除表的字段的原有约束 alter table 表名 add constraint 约 ...

  5. MySQL5.0+提示字段没有默认值(doesn’t have a default value)的解决方法

    方法一: 打开my.ini,查找  sql-mode=”STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION” 修改为  sql ...

  6. mysql字段默认值不生效的问题解决(上)

    在项目中使用mybatis做为持久层框架,mysql数据库.项目上线前,DBA要求我们将每张数据库表中的字段都设置默认值和not null.之前项目中有一些insert语句是将表中所有字段都列出来,然 ...

  7. 【备忘】SQL语句增加字段、修改字段、修改类型、修改默认值

    一.修改字段默认值 alter table 表名 drop constraint 约束名字 ------说明:删除表的字段的原有约束 alter table 表名 add constraint 约束名 ...

  8. SQL修改字段默认值、获取字段默认值

    一.SQL修改字段默认值 alter table 表名 drop constraint 约束名字 说明:删除表的字段的原有约束 alter table 表名 add constraint 约束名字 D ...

  9. Mysql数据表字段设置了默认值,插入数据后默认字段的值却为null,不是默认值

    我将mysql的数据表的某个字段设置了默认值为1,当向该表插入数据的时候该字段的值不是默认值,而是null. 我的错误原因: 对数据库的操作我使用了持久化工具mybatis,插入数据的时候插入的是整个 ...

随机推荐

  1. JavaScript 基础第三天

    一.前言 在前天的内容我们提到了有关于JS的一些语言结构,这些语言结构都是语法中最为基本的内容必须予以熟记并可以灵活掌握. 二.引入 在今天内容中我们将讨论两个很重要的概念,数组与函数. 三.重点内容 ...

  2. linux redmine 搭建

    redmine搭建过程参考:http://www.tuicool.com/articles/InMbym 注意事项: 配置文件必须以2个空格开始 启动(指定了端口,和绑定的IP): ruby bin/ ...

  3. Tableau:数据可视化之急速BI

    1.我们通过数据可视化,是为了从数据中寻找什么呢?三个方面:模式.关系和异常.不管图形表现的是什么,我们都要留心观察这三者.

  4. 如何向MyEclipse项目的文件夹中添加JSP页面?

    1.鼠标选中该文件夹:2.鼠标右键单击该文件夹,选择“new->file”菜单项,创建一个空白文件:3.将JSP页面的所有源代码全部复制到该文件4.单击工具栏的“保存”按钮

  5. 解剖SQLSERVER 第七篇 OrcaMDF 特性概述(译)

    解剖SQLSERVER 第七篇  OrcaMDF 特性概述(译) http://improve.dk/orcamdf-feature-recap/ 时间过得真快,这已经过了大概四个月了自从我最初介绍我 ...

  6. .Net Core CLI–Ubuntu 14安装

    sudo sh -c 'echo "deb [arch=amd64] http://apt-mo.trafficmanager.net/repos/dotnet/ trusty main&q ...

  7. Linux Ubuntu上手动安装.NET Core SDK

    今天重装了一台Linux服务器的Ubuntu 14.04系统,需要重新安装.NET Core 1.0. 按照官网上的文档用apt-get命令进行安装: sudo sh -c 'echo "d ...

  8. 我的前端架构之二--统一扩展Js方法

    我的前端架构汇总 MyJs_Core.js 这是一个核心的Js文件,它扩展了原生的Js方法.如下: Array对象: 1) indexOf 2) max 3) min 4) removeAt 5) i ...

  9. VS2012编译的Windows服务启动后立即停止的解决方案

    ATL中的BUG,在没有COM的服务中,使用_ATL_NO_COM_SUPPORT. 并在服务中添加下面的代码 #if defined(_ATL_NO_COM_SUPPORT) HRESULT Pre ...

  10. Java面向对象思想解决猜拳问题

    第一个面向对象的程序: 一个控制台猜拳小游戏: 第一步选择角色: 第二部选择剪刀,石头,布,与电脑进行PK: 第三部选择继续或者选择结束; 结束显示比赛的局数,以及各自赢得的分数: 设计思路 分析问题 ...