将datetime2数据类型转换为datetime数据类型会导致超出范围的值


379

我有一个包含5列的数据表,其中一行被数据填充,然后通过事务保存到数据库中。

保存时,返回错误:

从datetime2数据类型到datetime数据类型的转换导致值超出范围

从读取的角度看,它意味着DateTime2我的数据表的类型为,数据库为a DateTime;那是错的。

日期列设置为DateTime如下所示:

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

可以用代码解决此问题,还是必须在数据库级别进行某些更改?

Answers:


60

您在该栏中有什么样的日期?

它们是否都适合该类型的范围?


顺便说一句,TypeDataColumn构造函数获取对象的正确方法是typeof关键字,它的速度要快几个数量级。

因此,要创建列,您应该编写

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

3
我现在更改了数据列并使用了typeof。。。此外,我发现了我的问题。有1个数据行包含错误的日期,从而触发了错误
Gerbrand

739

如果您在字段不接受NULL值时未将值分配给DateTime字段,则会发生这种情况。

这为我解决了!


43
在Entity Framework中,如果添加的Created列不为null,则在未在代码中设置值的情况下更新EDMX,可能会以这种方式引发此错误
Brad Thomas

6
是什么为您解决的?当您有一个日期时间字段,并将getdate()调用作为默认值时,会出现此错误。
user3046061 2014年

15
为什么实体框架不能忽略是否为NULL,因为在我的SQL端,我有一个默认值= getdate()?
JoshYates1980 2014年

33
我相信发生的是EntityFramework看到DateTime.MinValue是0001年,并且在SQL中datetime超出范围值,因此它将此值作为DateTime2(支持0001年)发送,因此插入/更新有效。当SQL尝试将此DateTime2转换为DateTime时,它将失败,因为这将导致不同的值。两种解决方案是:1在模型中使用可为空的datetime或2.在保存上下文更改之前将所有datetime值初始化为正确的值。您做出的选择取决于日期时间在模型中的含义。
吉列尔莫·鲁菲诺

1
@GuillermoRuffino的解决方案为我工作。检查您的所有字段并找到那些0001年的条目。
Francesco B.

158

.NET中的DATETIME和都DATETIME2映射到System.DateTime-您实际上不能进行“转换”,因为它实际上是相同的.NET类型。

请参阅MSDN文档页面:http : //msdn.microsoft.com/zh-cn/library/bb675168.aspx

这两个的“ SqlDbType” 有两个不同的值-您可以在DataColumn定义中指定这些值吗?

但是:在SQL Server上,支持的日期范围完全不同。

DATETIME支持1753/1/1到“永恒”(9999/12/31),同时DATETIME2支持0001/1/1到永恒。

因此,您真正需要做的是检查日期中的年份-如果日期在1753年之前,则需要将其更改为1753年之后的日期,以便DATETIMESQL Server中的列可以处理它。


7
这解释了我遇到的问题。尽管在少数情况下需要处理1753/1/1之前的实际日期,但是在许多情况下会获得默认值0001/1/1可能会导致错误。

我确认当我尝试向'datetime'数据类型插入'new DateTime()'时,我收到了此异常。
George Onofrei'3

1
我试图在写入数据库的C#代码中分配默认值DateTime.MinValue。这解释了我遇到的错误。+1
Mkalafut

我使用Entity Framework Code First,并使用带有DateTime属性的模型。DtInit = new System.DateTime(1492, 10, 12),失败。
Kiquenet

这是真正原因隐藏在补丁后面的情况之一... +1
EugenioMiró18年

41

在我的SQL Server 2008数据库中,我有一DateTime列标记为不可为空,但其GetDate()功能为默认值。使用EF4插入新对象时,出现此错误是因为我没有在对象上明确传递DateTime属性。我希望SQL函数能够为我处理日期,但事实并非如此。我的解决方案是从代码发送日期值,而不是依靠数据库来生成日期值。

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

2
乐意效劳。这很烦人,因为您认为当从表中创建对象时,EF数据上下文将能够发现该字段具有默认值。
格雷厄姆

我想关于EF有很多事情。我正在使用POCO自我跟踪实体,它就是这样的集群。我要去看看代码第一种模式,如果这还充满废话,我认真考虑要回LINQ to SQL和使用对象映射到道具映射到我自己的实体...

2
两周前,我在VS Live上看到了EF Code First演示,顺便说一句,它看上去真棒。
格雷厄姆

那是好消息。我们很快将在我的办公室开始一个新项目,而我却选择了EF-CF和dapper(由SO使用/维护)。在通过WCF服务使用的应用程序中,可能会更好。

1
您好,一岁以上的评论!我本人是从EF Code-First开始的,发现在POCO上我只需要将datetime成员定义为Nullable<DateTime>,并且在代码中我可以将此字段保留为真正的null(而不是01/01/0000)。令我惊讶的是,EF to SQL知道忽略INSERT上的此null并使用服务器(GetDate())上的日期...对我们来说,这甚至更可取,因为我们需要更好的服务器一致性,而不必担心之间的时钟差异。 Web服务器和sql服务器。
Funka 2013年

34

对我来说是因为约会时间是

01/01/0001 00:00:00

在这种情况下,您想以我的FirstYearRegistered代码为例为EF DateTime对象分配null。

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

我正在使用ExcelDataReader解析此数据,并且在输入无效文本时返回了01/01/0001(不会如预期的那样引发异常-使用.GetDateTime(columnIndex)方法)。与MinValue的比较可以防止sql中发生超出范围的异常。
Tommy 2014年

22

这个让我发疯。我想避免使用可为空的日期时间(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

21

有时EF不知道这是在处理计算列触发器。通过设计,这些操作将在插入后在EF之外设置一个值。

解决方法是Computed在EF edmx中为StoreGeneratedPattern属性中的该列指定。

对我而言,是当该列具有插入当前日期和时间的触发器时,请参阅下文的第三部分。


解决步骤

在Visual Studio中,打开Model Browser页面,Model然后Entity Types->然后

  1. 选择实体和日期时间属性
  2. 选择 StoreGeneratedPattern
  3. 设置 Computed

EF模型浏览器“模型实体类型”对话框


对于这种情况,其他答案是解决方法,对于该列,其目的是在创建记录时指定时间/日期,这是SQL执行触发器以添加正确时间的工作。如下面的SQL触发器:

DEFAULT (GETDATE()) FOR [DateCreated]


请注意,我使用GETDATE()了当时的字面意思。但是最近有评论说SYSDATETIME(),我认为应该对任何DateTime2操作使用它。
ΩmegaMan

10

我遇到了这个问题,并在datetime属性中添加了以下内容:

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

1
using System.ComponentModel.DataAnnotations.Schema; 是必需的
Kiquenet '17

9

如果我们不传递日期时间到日期时间字段,则将传递默认日期{1/1/0001 12:00:00 AM}。

但是此日期与实体框架工作不兼容,因此它将引发 datetime2数据类型到datetime数据类型的转换,导致值超出范围

default DateTime.now如果您没有传递任何日期,请仅输入日期字段。

movie.DateAdded = System.DateTime.Now

我会说将“ DateTime.Now”作为默认值传递是远远不够的,并且会产生误导。
Bartosz

6

最简单的方法是将数据库更改为使用datetime2而不是datetime。兼容性很好,并且不会出错。

您仍然需要进行大量测试...

该错误可能是因为您试图将日期设置为0年或类似的东西-但这全都取决于您可以更改内容的位置。


4

我发现这篇文章试图弄清楚为什么我一直收到以下错误,其他答案对此进行了解释。

从datetime2数据类型到datetime数据类型的转换导致值超出范围。

使用可为空的DateTime对象。
公开DateTime?PurchaseDate {get; 组; }

如果使用实体框架,则将edmx文件中的nullable属性设置为True。

将edmx文件中的nullable属性设置为** True **。


3

正如andyuk已经指出的那样,当将NULL值分配给不可为空的DateTime字段时,可能会发生这种情况。考虑将DateTime更改为DateTime吗?Nullable < DateTime >。请记住,如果您使用的是Dependency Property,还应确保您的依赖项属性的类型也是可空的DateTime类型。

以下是不完整的DateTimeDateTime的真实示例类型调整引起奇怪的行为

在此处输入图片说明


2

实体框架4使用datetime2数据类型,因此在db中,SQL Server 2008的相应字段必须为datetime2。

要获得解决方案,有两种方法。

  1. 要在实体框架4中使用日期时间数据类型,必须将edmx文件中的ProviderManifestToken切换为“ 2005”。
  2. 如果将相应的字段设置为Allow Null(将其转换为NULLABLE),则EF会自动使用日期对象作为datetime。

1
我为数据库模型(POCO类)选择了第二点,并想知道如何将字段设置为可为空的类型。如果有人想知道,您可以通过在日期类型之后添加问号(?)来实现。例如公共DateTime?StartTime {get; 组; }这为我解决了这个问题。我只需要做的另一件事就是将TimeSpan转换放在一行代码中,在这些代码中我彼此减去两个可为null的DateTime值。例如var timeTaken =(TimeSpan)(endTime-startTime);
Ciaran Gallagher 2013年

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.)
 }

1

在模型类的属性上添加以下提到的属性。

Attribute = [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
Reference = System.ComponentModel.DataAnnotations.Schema

最初,我忘记添加此属性。所以在我的数据库中创建了约束

ALTER TABLE [dbo].[TableName] ADD DEFAULT (getdate()) FOR [ColumnName]

我添加了此属性并更新了我的数据库,然后将其更改为

ALTER TABLE [dbo].[TableName] ADD CONSTRAINT [DF_dbo.TableName_ColumnName] DEFAULT (getdate()) FOR [ColumnName]

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
Ajith Chandran


0

有时,它在开发机器上可以正常运行,而不能在服务器上运行。就我而言,我必须输入:

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

在web.config文件中。

机器(服务器)中的时区正确(在CO语言环境中),但Web应用程序不正确。此设置完成,并且再次正常运行。

当然,所有日期都很有价值。

:D


0

将此代码添加到ASP.NET中的类可以使我工作:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}

0

我知道这个问题,你们所有人也应该这样做:

https://zh.wikipedia.org/wiki/年_2038_problem

在SQL中,创建了一个新的字段类型来避免此问题(datetime2)。

此“日期”字段类型具有与DateTime .Net类相同的范围值。它会解决您所有的问题,所以我认为解决该问题的最佳方法是更改​​数据库列类型(不会影响您的表数据)。


0

请检查以下两个:1)该字段没有NULL值。例如:

 public DateTime MyDate { get; set; }

替换为:

public DateTime MyDate { get; set; }=DateTime.Now;

2)再次新建数据库。例如:

db=new MyDb();

如果您不希望该值为DateTime.Now,该怎么办?
野蛮

如果您不想:DateTime.Now。您可以使用:new DateTime(...,...,...)
RainyTears


0

当我想编辑页面usnig ASP.Net MVC时,我看到此错误。创建数据库时没有问题,但更新数据库使DateCreated属性超出范围!

如果您不希望DateTimeProperty为Nullable,并且不想检查其值是否在sql DateTime范围内(并且@Html.HiddenFor无济于事!),只需static DateTime在相关类(Controller)内添加一个字段,并在GET正在运行,然后在POST完成工作时使用它:

public class PagesController : Controller
{
    static DateTime dateTimeField;
    UnitOfWork db = new UnitOfWork();

    // GET:
    public ActionResult Edit(int? id)
    {
        Page page = db.pageRepository.GetById(id);
        dateTimeField = page.DateCreated;
        return View(page);
    }

    // POST: 
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(Page page)
    {
        page.DateCreated = dateTimeField;
        db.pageRepository.Update(page);
        db.Save();
        return RedirectToAction("Index");

    }
}

0

我在一个简单的控制台应用程序项目中遇到了这个问题,我的快速解决方案是通过运行此方法将任何可能的datetime2日期转换为可为空的日期时间:

static DateTime? ParseDateTime2(DateTime? date)
    {
        if (date == null || date.ToString() == "1/1/0001 12:00:00 AM")
        {
            return null;
        }
        else
        {
            return date;
        }
    }

这当然不是一种完全综合的方法,但是它可以满足我的需求,也许会对其他人有所帮助!


0

检查数据库中的请求格式。例如我的数据库具有默认值或绑定(((1)/(1))/(1900))

System.DateTime MyDate = new System.DateTime( 1900 ,1, 1);

在此处输入图片说明


-1

您将拥有日期列,该列设置为lesathan允许的dattime的最小值,例如1/1/1001。

为了克服这个问题,您可以为ur属性设置正确的datetime值,还可以设置另一个神奇的属性,例如IsSpecified = true。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.