今天在用EF做插入操作的時候發現數據庫中一個datetime類型的字段(CreateDate)的值居然全部為null。於是趕緊看表結構發現CreateDate字段居然是允許為空的。
雖然為空,但是設置了默認值getdate(),按說不應該為null的。於是開始測試。
字段允許Null值的情況
Users表結構如下:

假如一個字段有了默認值,並且又允許為Null,在做插入操作時會發生什么?
如上圖中的表結構,CreateDate是允許為null的,而又有默認值getdate()。這樣在用傳統SQL語句和EF做插入操作時分別會發生什么呢?
先看傳統SQL語句:
|
1
|
insert
into
Users(Username,
Password
)
values
(
'test'
,
'123456'
)
|
插入結果:

使用SQL完全沒有問題。
再看使用EF:
|
1
2
3
4
5
6
7
|
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理所當然地一切正常:
|
1
|
insert
into
Users(Username,
Password
)
values
(
'admin'
,
'123456'
)
|

那再看下用EF:
|
1
2
3
4
5
6
7
|
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”!管你有沒有默認值!那也不至於拋異常啊,頂多字段值存儲為“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。
除此之外是否還有別的方法呢?
方法是有的,打開EF的.edmx文件,找到<EntityType Name="表名">節點,把如下節點:
<Property Name="CreateDate" Type="datetime" Nullable="false" />
改成:
<Property Name="CreateDate" Type="datetime" Nullable="false" StoreGeneratedPattern="Identity" />
即可。
