将datetime2数据类型转换为日期时间数据类型会导致超出范围的值

时间:2009-08-26 00:39:55

标签: c# sql-server entity-framework datetime orm

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

保存时,会返回错误:

  

将datetime2数据类型转换为日期时间数据类型会导致超出范围的值

如上所述,它意味着我的数据表的类型为DateTime2,而我的数据库为DateTime;那是错的。

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

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

问题

这可以在代码中解决,还是必须在数据库级别更改某些内容?

26 个答案:

答案 0 :(得分:680)

当字段不接受 NULL 时,如果您没有为 DateTime 字段分配值,就会发生这种情况价值观。

为我修好了!

答案 1 :(得分:144)

.NET中的DATETIMEDATETIME2映射到System.DateTime - 您无法真正进行“转换”,因为它实际上是相同的.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列能够处理它。

马克

答案 2 :(得分:50)

您在专栏中有哪些日期?

是否所有这些都适合该类型的范围?


另外,为Type构造函数获取DataColumn对象的正确方法是typeof关键字,这个关键字要快几个数量级。

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

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

答案 3 :(得分:40)

在我的SQL Server 2008数据库中,我将DateTime列标记为不可为空,但使用GetDate()函数作为其默认值。使用EF4插入新对象时,我收到此错误,因为我没有显式地在我的对象上传递DateTime属性。我期望SQL函数为我处理日期,但事实并非如此。我的解决方案是从代码发送日期值,而不是依赖于数据库来生成它。

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

答案 4 :(得分:27)

对我来说这是因为日期时间是..

  

01/01/0001 00:00:00

在这种情况下,您希望使用我的FirstYearRegistered代码作为示例为您分配EF DateTime对象...

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

答案 5 :(得分:19)

有时EF不知道处理计算列触发器。按照设计,这些操作将在插入后设置EF之外的值。

修复方法是在Computed属性中为该列指定EF edmx中的StoreGeneratedPattern

对我而言,当列有一个插入当前日期和时间的触发器时,请参见下面的第三部分。


要解决的步骤

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

  1. 选择实体和日期时间属性
  2. 选择StoreGeneratedPattern
  3. 设为Computed
  4. EF Model Browser Model Entity Type dialog


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

    DEFAULT (GETDATE()) FOR [DateCreated]

答案 6 :(得分: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;
                    }
                }
            }
        }
    }
}

答案 7 :(得分:9)

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

但是这个日期与实体框架工作不兼容,所以它会抛出 将datetime2数据类型转换为日期时间数据类型会导致超出范围的值

如果您没有通过任何日期,只需default DateTime.now到日期字段。

movie.DateAdded = System.DateTime.Now

答案 8 :(得分:9)

我遇到了这个并将以下内容添加到我的datetime属性中:

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

答案 9 :(得分:6)

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

你仍然想做一堆测试...

错误可能是因为你试图将日期设置为0年级或者其他东西 - 但这一切都取决于你可以控制更改内容的位置。

答案 10 :(得分:4)

我发现这篇文章试图找出为什么我一直得到以下错误,这是由其他答案解释的。

将datetime2数据类型转换为日期时间数据类型会导致超出范围的值。

使用可以为空的DateTime对象。
    公共日期时间? PurchaseDate {get;组; }

如果您使用的是实体框架 将edmx文件中的可空属性设置为 True

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

答案 11 :(得分:3)

正如http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/已经指出的那样,当 NULL 值分配给不可为空的 DateTime 字段时,可能会发生这种情况。考虑将日期时间更改为日期时间?可以为空的&lt; 日期时间&gt;。请记住,如果您使用的是andyuk,还应确保您的依赖项属性的类型也是可以为空的DateTime类型。

下面是一个不完整的日期时间日期时间?类型调整的实际例子,它会引发奇怪的行为

Dependency Property

答案 12 :(得分:2)

Entity Framework 4使用datetime2数据类型,因此在db中,对应的字段必须是SQL Server 2008的datetime2。

要实现解决方案,有两种方法。

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

答案 13 :(得分: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.)
 }

答案 14 :(得分: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]

答案 15 :(得分:0)

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

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

enter image description here

答案 16 :(得分:0)

对我来说,我有一个Devexpress DateEdit组件,该组件通过Nullable模型属性绑定到可空的datetime MSSQL列。我要做的就是在DateEdit上设置AllowNullInput = True。将其设置为“默认”会导致日期1.1.0001出现-仅在离开DateEdit之前-然后由于上述后续说明,我收到了此转换错误消息。

答案 17 :(得分:0)

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

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

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

答案 18 :(得分:0)

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

当您不希望您的DateTime属性为Nullable,并且不想检查其值是否在sql DateTime范围内(并且@Html.HiddenFor无效!)时,只需添加一个在相关类(控制器)内的static DateTime字段中,并在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");

    }
}

答案 19 :(得分:0)

具有继承的datetime属性的问题

当不可为空的日期字段在插入/更新时值为null时,通常会显示此错误消息。原因之一可能是继承。

如果您的日期是从基类继承的,并且您没有进行映射,则EF不会读取其值。

有关更多信息: https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines

答案 20 :(得分:0)

检查以下两个:

1)该字段没有NULL值。例如:

<div id="growler">
     <h2> {{ appName }} </h2>
</div>

替换为:

public DateTime MyDate { get; set; }

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

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

答案 21 :(得分:0)

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

https://en.wikipedia.org/wiki/Year_2038_problem

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

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

答案 22 :(得分:0)

将此代码添加到ASP.NET中的类中对我有用:

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

答案 23 :(得分:0)

有时它在开发机器上运行良好,而在服务器中运行良好。在我的情况下,我不得不说:

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

在web.config文件中。

计算机(服务器)中的时区是正确的(到CO语言环境),但Web应用程序没有。完成此设置,它再次正常工作。

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

:d

答案 24 :(得分:0)

在我的情况下,我们将日期转换为日期时间,我们得到了这个错误。 What happens is that Date has a "more programmer oriented" minimum of 01/01/0001, while Datetime is stuck at 1753

将此与我们的数据收集错误相结合,您就会得到异常!

答案 25 :(得分:-2)

您将拥有日期列,该列被设置为小于允许数据时间的最小值,如1/1/1001。

要克服此问题,您可以将正确的日期时间值设置为ur属性,并设置另一个神奇的属性,如IsSpecified = true。