2009-08-26 95 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

相关问题