場景:
ASP.NET MVC項目中,使用entity framework添加數據遇到“從 datetime2 數據類型到 datetime 數據類型的轉換產生一個超出范圍的值”這個錯誤問題。后經過問題的排查,是由於C#代碼中實體類所傳入的DateTime類型屬性沒有賦值的原因,其中主要涉及到SQL Server 中datetime2的時間精度和日期范圍的問題。
條件分析:
- SQL Server數據庫版本中有datetime2類型
- 數據庫中,某個要進行添加或者修改操作的字段的數據類型為datetime,比如表Table1中的InputDate字段,類型為datetime。
- 后台代碼進行數據庫操作時,傳入的實體對象的DateTime類型的屬性沒有賦值,比如有一實體類Test,該類下有個InputDate屬性,類型為DateTime。
- 最后使用entity framework對這個dateime類型的字段進行添加和修改操作就會出現此問題
兩者之間的區別:
這里值的注意的是datetime2的日期范圍是"0001-01-01 到 9999-12-31"(公元元年 1 月 1 日到公元 9999 年 12 月 31 日)。而datetime的日期范圍是:”1753 年 1 月 1 日到 9999 年 12 月 31 日“。這里的日期范圍就是造成“從 datetime2 數據類型到 datetime 數據類型的轉換產生一個超出范圍的值”這個錯誤的原因!!!
在c#中,如果實體類的屬性沒有賦值,一般都會取默認值,比如int類型的默認值為0,string類型默認值為null, 那DateTime的默認值呢?由於DateTime的默認值為"0001-01-01",所以entity framework在進行數據庫操作的時候,在傳入數據的時會自動將原本是datetime類型的數據字段轉換為datetime2類型(因為0001-01-01這個時間超出了數據庫中datetime的最小日期范圍),然后在進行數據庫操作。問題來了,雖然EF已經把要保存的數據自動轉為了datetime2類型,但是數據庫中表的字段還是datetime類型!所以將datetime2類型的數據添加到數據庫中datetime類型的字段里去,就會報錯並提示轉換超出范圍。
解決方案:
- C#代碼中 DateTime類型的字段在作為參數傳入到數據庫前記得賦值,並且的日期要大於1753年1月1日。
- C#代碼中 將原本是DateTime類型的字段修改為DateTime?類型,由於可空類型的默認值都是為null,所以傳入數據庫就可以不用賦值,數據庫中的datetime類型也是支持null值的。
- 修改數據庫中表的字段類型,將datetime類型修改為datetime2類型