2009-08-26 90 views
266

我有一個帶有5列的數據表,其中一行正在填充數據,然後通過事務保存到數據庫。將datetime2數據類型轉換爲日期時間數據類型會導致超出範圍的值

同時節約,則返回一個錯誤:

一個DATETIME2數據類型爲datetime數據類型的轉換導致外的範圍內的值

它意味着,作爲讀,我的數據表有一個類型DateTime2和我的數據庫a DateTime;那是錯的。

日期列設置爲DateTime這樣的:

new DataColumn("myDate", Type.GetType("System.DateTime"))

問題

可以這樣用代碼來解決或有些事情是不是在數據庫級別是否會改變?

回答

44

你有什麼樣的日期在列中?

是否所有這些都符合該類型的範圍?


順便說一句,得到的DataColumn構造一個Type對象的正確方法是typeof關鍵字,這是快幾個數量級。

因此,創建列,你應該寫

new DataColumn("myDate", typeof(DateTime)) 
+2

我改變了我的datacolumns和現在使用typeof ...進一步,我發現我的問題。有1個datarow包含錯誤的日期,從而觸發了錯誤 – Gerbrand 2009-08-26 05:46:33

5

最簡單的事情是將數據庫更改爲使用datetime2而不是datetime。兼容性很好,你不會得到你的錯誤。

你還是要做一堆的測試...

的錯誤可能是因爲你想的日期設置爲0年或東西 - 但是這一切都取決於你有控制改變東西。

122

無論是DATETIMEDATETIME2地圖System.DateTime在.NET - 你不能真正做一個「轉換」,因爲它是真的一樣.NET類型。

請參閱MSDN文檔頁面:http://msdn.microsoft.com/en-us/library/bb675168.aspx

有對於「SqlDbType」兩個不同的值,這兩個 - 你可以指定那些在您DataColumn定義是什麼?

但是:在SQL Server上,支持的日期範圍相當不同。

DATETIME支持1753/1/1到「永恆」(9999/12/31),而DATETIME2支持0001/1/1到永恆。

因此,您真正需要做的是檢查日期的年份 - 如果它在1753年之前,則需要將其更改爲1753年之後的某個值,以便SQL Server中的DATETIME列能夠處理它。

馬克

+4

這解釋了我的問題。儘管1753/1/1之前的實際日期需要處理的情況很少,但是在許多情況下,可以得到可能導致錯誤的默認值0001/1/1。 – Hong 2012-06-18 14:11:43

+0

我確認當我試圖向'datetime'數據類型插入'new DateTime()'時,我收到了這個異常。 – 2015-03-01 08:59:31

+0

我試圖在寫入數據庫的C#代碼中分配DateTime.MinValue的默認值。這解釋了我得到的錯誤。 +1 – Mkalafut 2016-12-06 19:42:21

574

,如果你不賦值給一個DateTime字段時,該字段不接受NULL值會發生這種情況。

爲我修好了!

+33

在實體框架中,如果添加一個非空的創建列,那麼更新您的EDMX,當您沒有在代碼中設置值時,可能會以這種方式拋出此錯誤 – 2013-01-19 23:28:23

+4

什麼修復了它?當您將日期時間字段的getdate()調用作爲默認值時,會出現此錯誤。 – user3046061 2014-07-21 18:56:06

+10

爲什麼實體框架不能忽略NULL,因爲在我的SQL端,我有一個默認值= getdate()? – JoshYates1980 2014-09-26 19:29:05

37

在我的SQL Server 2008數據庫中,我有一個DateTime列標記爲不可空,但GetDate()函數作爲其默認值。當使用EF4插入新對象時,我得到了這個錯誤,因爲我沒有明確地在我的對象上傳遞DateTime屬性。我希望SQL函數能夠爲我處理日期,但事實並非如此。我的解決方案是從代碼發送日期值,而不是依賴數據庫來生成它。

obj.DateProperty = DateTime.now; // C# 
+2

很高興幫助。這很煩人,因爲當從表中創建對象時,您會認爲EF數據上下文將能夠發現該字段具有默認值。 – Graham 2011-08-10 13:19:42

+0

我會想很多關於EF的事情。我正在使用POCO自我跟蹤實體,它就是這樣一個羣集。我要檢查代碼的第一個模型,如果這也充滿了廢話,我正在認真思考要回到LINQ到SQL和使用對象映射器來將道具映射到我自己的實體... – Will 2011-08-10 17:20:27

+2

我看到在2周前的VS Live的EF Code First演示,它看起來非常棒,順便說一句。 – Graham 2011-10-31 18:07:29

2

實體框架4工程與DATETIME2數據類型,因此在數據庫中的對應字段必須DATETIME2 SQL Server 2008年

爲了更好地實現該解決方案有兩種方法。

  1. 要在Entity Framwork 4中使用datetime數據類型,您必須將edmx-file中的ProviderManifestToken切換爲「2005」。
  2. 如果您將相應的字段設置爲Allow Null(將其轉換爲NULLABLE),那麼EF會自動使用日期對象作爲日期時間。
+1

我拿起你的第二點爲我的數據庫模型(POCO類),並想知道如何將字段設置爲可空類型。如果有人想知道,可以通過在日期類型後添加一個問號(?)來做到這一點。例如公共DateTime? StartTime {get;組; } 這解決了我的問題。我只需要做的其他事情就是在一行代碼中放置一個TimeSpan,我將兩個可空的DateTime值相互減去。 例如var timeTaken =(TimeSpan)(endTime - startTime); – 2013-03-16 15:39:28

18

這一個讓我瘋狂。我想避免使用空的日期時間(DateTime?)。我沒有使用SQL Server 2008的datetime2類型要麼

modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2"); 

的選項,我最終還是選擇了以下內容:

public class MyDb : DbContext 
{ 
    public override int SaveChanges() 
    { 
     UpdateDates(); 
     return base.SaveChanges(); 
    } 

    private void UpdateDates() 
    { 
     foreach (var change in ChangeTracker.Entries<MyEntityBaseClass>()) 
     { 
      var values = change.CurrentValues; 
      foreach (var name in values.PropertyNames) 
      { 
       var value = values[name]; 
       if (value is DateTime) 
       { 
        var date = (DateTime)value; 
        if (date < SqlDateTime.MinValue.Value) 
        { 
         values[name] = SqlDateTime.MinValue.Value; 
        } 
        else if (date > SqlDateTime.MaxValue.Value) 
        { 
         values[name] = SqlDateTime.MaxValue.Value; 
        } 
       } 
      } 
     } 
    } 
} 
+1

使用'[Column(TypeName =「datetime2」)]'? – Kiquenet 2017-07-02 17:37:44

26

對我來說,那是因爲日期時間是..

01/01/0001 00:00:00

在這種情況下you wan噸至null分配給你EF DateTime對象......用我FirstYearRegistered代碼爲例

DateTime FirstYearRegistered = Convert.ToDateTime(Collection["FirstYearRegistered"]); 
if (FirstYearRegistered != DateTime.MinValue) 
{ 
    vehicleData.DateFirstReg = FirstYearRegistered; 
} 
+0

我使用ExcelDataReader解析這些數據,並且在輸入無效文本時不返回01/01/0001(不會像預期的那樣拋出異常 - 使用.GetDateTime(columnIndex)方法)。與MinValue的比較做了一些技巧來防止sql中超出範圍的異常。 – Tommy 2014-01-14 02:40:26

0

有時它可以在開發機器,而不是在服務器罰款。在我的情況下,我不得不說:

<globalization uiCulture="es" culture="es-CO" /> 

在web.config文件中。

機器(服務器)中的時區是正確的(對於CO語言環境),但Web應用程序沒有。這個設置完成了,它再次正常工作。

當然,所有日期都有價值。

:D

1

基於@ sky-dev實現創建基類。所以這可以很容易地應用於多個上下文和實體。

public abstract class BaseDbContext<TEntity> : DbContext where TEntity : class 
{ 
    public BaseDbContext(string connectionString) 
     : base(connectionString) 
    { 
    } 
    public override int SaveChanges() 
    { 

     UpdateDates(); 
     return base.SaveChanges(); 
    } 

    private void UpdateDates() 
    { 
     foreach (var change in ChangeTracker.Entries<TEntity>()) 
     { 
      var values = change.CurrentValues; 
      foreach (var name in values.PropertyNames) 
      { 
       var value = values[name]; 
       if (value is DateTime) 
       { 
        var date = (DateTime)value; 
        if (date < SqlDateTime.MinValue.Value) 
        { 
         values[name] = SqlDateTime.MinValue.Value; 
        } 
        else if (date > SqlDateTime.MaxValue.Value) 
        { 
         values[name] = SqlDateTime.MaxValue.Value; 
        } 
       } 
      } 
     } 
    } 
} 

用法:

public class MyContext: BaseDbContext<MyEntities> 
{ 

    /// <summary> 
    /// Initializes a new instance of the <see cref="MyContext"/> class. 
    /// </summary> 
    public MyContext() 
     : base("name=MyConnectionString") 
    { 
    } 
    /// <summary> 
    /// Initializes a new instance of the <see cref="MyContext"/> class. 
    /// </summary> 
    /// <param name="connectionString">The connection string.</param> 
    public MyContext(string connectionString) 
     : base(connectionString) 
    { 
    } 

    //DBcontext class body here (methods, overrides, etc.) 
} 
6

我遇到了這一點,並增加了以下我的日期時間屬性:

[Column(TypeName = "datetime2")] 
public DateTime? NullableDateTimePropUtc { get; set; } 
+1

'使用System.ComponentModel.DataAnnotations.Schema;'***是必需的*** – Kiquenet 2017-07-02 17:46:36

17

有時EF不知道這是處理一個計算列觸發器。按照設計,這些操作將在插入後在EF之外設置一個值。

修復方法是在EF的edmx中指定StoreGeneratedPattern屬性中該列的Computed

對我來說,這是當列有一個觸發器插入當前的日期和時間,見下面的第三部分。


步驟解決

在Visual Studio中打開Model Browser頁,然後Model然後Entity Types - >然後

  1. 選擇實體和日期時間屬性
  2. 選擇StoreGeneratedPattern
  3. 設爲Computed

EF Model Browser Model Entity Type dialog


對於這種情況,其他的答案是解決方法,該列的目的是有記錄的創建時指定一個時間/日期,那就是SQL的作業執行觸發器以添加正確的時間。如此SQL觸發器:

DEFAULT (GETDATE()) FOR [DateCreated]

+0

太棒了!確切地說,我有這個問題。謝謝! – 2017-02-03 12:33:18

+0

請注意,我曾經使用'GETDATE()',這是我當時所做的。但最近有人發表評論說,應該對任何我認爲是正確的DateTime2操作使用'SYSDATETIME()'。 – OmegaMan 2018-02-23 14:57:36

-1

您將擁有設置爲允許數據時間的最小值(例如1/1/1001)的日期列。

爲了克服這個問題,你可以設置適當的日期時間值爲你的屬性,也可以設置另一個神奇的屬性,如IsSpecified = true。

3

我發現這篇文章試圖找出爲什麼我不斷收到以下錯誤,這是由其他答案解釋。

一個DATETIME2數據類型爲datetime數據類型的轉換導致外的範圍內的值。

使用一個可空DateTime對象。
public DateTime? PurchaseDate {get;組; }

如果您正在使用實體框架 在EDMX文件可空屬性設置爲

Set the nullable property in the edmx file to **True**

2

正如andyuk早已指出的手續,這可能發生一個NULL值時被分配給不可空的DateTime字段。考慮將日期時間更改爲DateTime?可空 < 日期時間>。請記住,如果您使用的是Dependency Property,還應該確保您的依賴屬性的類型也是可以爲空的DateTime類型。

下面是一個不完整的現實生活中的例子DateTimeDateTime?型調整引發此異常行爲

enter image description here

2

如果我們不日期時間傳遞到日期時間字段的默認日期{1/1/0001 12:00:00 AM}將被傳遞。

但這個日期是不是與實體框架的工作兼容,所以它會拋出 轉化DATETIME2數據類型爲datetime數據類型導致超出範圍的值

只是default DateTime.now的日期字段,如果你沒有通過任何日期。

movie.DateAdded = System.DateTime.Now 
+0

這是正確的 – Zac 2017-09-04 00:32:34

相關問題