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

455
我有一个包含5列的datatable,在将一行填充数据后通过事务保存到数据库时出现了错误。在保存时,返回了一个错误:

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

这意味着,根据所读取的内容,我的datatable具有DateTime2类型,而我的数据库具有DateTime类型;这是错误的。
日期列被设置为 DateTime,代码如下: new DataColumn("myDate", Type.GetType("System.DateTime")) 问题:
这个问题可以在代码中解决还是需要在数据库层面上进行更改?
27个回答

3
正如andyuk所指出的那样,当给非可空的DateTime字段赋值为NULL值时,就会出现这种情况。考虑将DateTime更改为DateTime?Nullable<DateTime>。请注意,如果您正在使用依赖属性(Dependency Property),还应确保您的依赖属性类型也是可空的DateTime类型。

以下是一个实际的例子,演示了从不完整的DateTime调整为DateTime?类型而引发的奇怪行为:

enter image description here


2

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

要解决这个问题有两种方法。

  1. 要在Entity Framework 4中使用datetime数据类型,您必须将edmx文件中的ProviderManifestToken切换为“2005”。
  2. 如果将相应字段设置为允许为空(它会将其转换为NULLABLE),那么EF自动将使用日期对象作为datetime。

1
我注意到了你提到的第二点,想知道如何将字段设置为可空类型。如果有人想知道,可以在日期类型后面加上一个问号(?)来实现。例如:public DateTime? StartTime { get; set; }这对我解决了问题。我需要做的另一件事是,在我从彼此减去两个可空的 DateTime 值的代码行周围放置一个 TimeSpan 转换。例如:var timeTaken = (TimeSpan) (endTime - startTime); - Ciaran Gallagher

2
在您的模型类属性上添加以下提到的属性。
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

1

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

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

这并不是一个完全全面的方法,但它适合我的需求,并且可能会帮助其他人!

这让我意识到我的审计功能没有在模型上运行,因为默认日期值没有被触及。这可能不是答案的预期用途,但它是让我茅塞顿开的线索。DateTime 的默认值在插入时超出范围。撤销所有操作,我只是简单地忘记在我们的模型类上实现审计信息接口... 经过漫长的一天,这可能很难找到... - Hunter-Orionnoir

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

在我的情况下,当为可空日期时间列显式分配NULL值,然后尝试保存更改时,将弹出此错误。


0

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

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

enter image description here


0
将以下代码添加到ASP.NET类中,对我很有效:

Adding this code to a class in ASP.NET worked fort me:

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

0
有时在开发机器上能够正常运行,但在服务器上却不能。就我而言,我不得不加上:<:/ p>
<globalization uiCulture="es" culture="es-CO" />

在 web.config 文件中。
机器(服务器)的时区是正确的(对于 CO 区域设置),但 Web 应用程序不是。进行此设置后,它再次正常工作。
当然,所有日期都有值。
:D

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接