将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围 - 未使用 DateTime2

Posted

技术标签:

【中文标题】将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围 - 未使用 DateTime2【英文标题】:The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value - no DateTime2 used 【发布时间】:2015-01-21 07:59:40 【问题描述】:

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

我的应用程序最近开始显示此错误,这很奇怪,因为它之前工作过。我没有更改“Word”模型中与 DateTime 相关的任何内容。当我将新模型添加到我的项目中时,它就开始发生了。

当我尝试编辑数据时出现服务器错误。创建和删除工作正常。

控制器:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "ID,UsersLanguage,OtherLanguage,Notes")] Word word, int idOfCollection)
    
        if (ModelState.IsValid)
        
            db.Entry(word).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index", new  idOfCollection = idOfCollection );
        
        return View(word);
    

型号:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace WebLanguageTeacher.Models.MyDatabase

    public class Word
    
        public int ID  get; set; 
        [MinLength(2, ErrorMessage = "Wydaje mi się, że słowo powinno mieć przynajmniej 2 litery ;)")] 
        [DisplayName("Język Użytkownika")]
        [Required]
        public string UsersLanguage  get; set; 
        [MinLength(2, ErrorMessage = "Wydaje mi się, że słowo powinno mieć przynajmniej 2 litery ;)")] 
        [DisplayName("Inny język")]
        [Required]
        public string OtherLanguage  get; set; 
        [DisplayName("Notatki")]
        public string Notes  get; set; 
        [DisplayName("Ostatnia powtórka")]
        public DateTime LastReviewed  get; set; 
        [DisplayName("Następna powtórka")]
        public DateTime NextReview  get; set; 
        [DefaultValue(0)]
        [DisplayName("Przerwa między powtórkami")]
        public int ReviewInterval  get; set;  /*W miejsce Difficulty*/

        [DisplayName("Nazwa właściciela")]
        public string OwnerName  get; set; 
        public virtual Collection Collection  get; set; 

        [NotMapped]
        public bool ModifyReview  get; set;  /* Klient przesyła tylko za ile dni będzie następna powtórka, serwer sam generuje datę*/

        public Word()
            ModifyReview = false;
        
    

怎么了?我没有创建任何 DateTime2 变量,为什么我的应用会尝试将 DateTime2 转换为 DateTime?

我将 ASP.net MVC 与 EntityFramework 一起使用。

【问题讨论】:

c# conversion of a datetime2 data type to a datetime data type的可能重复 调用SaveChanges()之前LastReviewedNextReview的实际值是多少? 某些日期时间字段在数据库中可以为空? @azhar_SE_nextbridge:不,这些文件都不能为空 可能您的一个或多个DateTime 值的值超出了SQL DATETIME 变量的范围(例如:如果它的默认值为DateTime.MinValue)。尝试使用调试器单步执行并检查 LastReviewed / NextReview 的值。 【参考方案1】:

当 DateTime 对象的值未明确设置时,它默认为 DateTime.MinValue。

因此,您的模型中有一个 DateTime 对象,该对象未设置并且默认为该对象,如上所述,它超出了 DateTime dbtype 的范围,因此 EntityFramework 将其转换为 DateTime2 dbtype,然后导致数据库中的转换错误。

要解决此问题,请检查模型中的所有 DateTime 对象,并确保将它们设置为 DateTime.MinValue 以外的任何内容。如果您不想将值设置为任何值,则在您的数据库和模型中将该字段设为可为空,然后一切都会正常

注意,在 db 列上设置默认值并不能解决这个问题,转换发生得太早,您必须显式设置值

【讨论】:

【参考方案2】:

日期时间范围:1753 年 1 月 1 日 - 9999 年 12 月 31 日

DateTime2 范围:0001-01-01 - 9999-12-31

使用下面的代码以避免冲突。

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
 
  modelBuilder.Entity<Word>().Property(o => o.NextReview).HasColumnType("datetime2");
 

【讨论】:

为什么我必须以这种奇怪的方式做这件事?我不能在创建变量时以某种方式声明它吗?像“public DateTime2 LastReviewed get; set; ” 在你的 DBContext 类中。 msdn.microsoft.com/en-us/library/…【参考方案3】:

使 datetime 可以为空,您需要明确地强制它们。就像如果属性“LastReviewed”可以为空,你应该像下面这样声明它。

[DisplayName("Ostatnia powtórka")]
public DateTime? LastReviewed  get; set; 

如果它们可以为空,则与其他日期时间变量相同

【讨论】:

但我不想让它可以为空。我需要设置它,它是这里最重要的变量之一。 默认情况下,如果您想为其分配值,它会为该日期时间对象分配最小值,然后以防您分配值但映射不正确,这就是发生此错误的原因...【参考方案4】:

如果您不希望更改日期时间字段(以及您不想修改的所有其他字段),则需要保留它们的旧值。为此,从数据库中检索旧实体,只需更改编辑表单中更新的字段。例如:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,UsersLanguage,OtherLanguage,Notes")] Word word, int idOfCollection)

    if (ModelState.IsValid)
    
        var dbWord = db.Words.Find(word.ID);
        dbWord.UsersLanguage = word.UsersLanguage;
        dbWord.OtherLanguage = word.OtherLanguage;
        dbWord.Notes = word.Notes;

        db.SaveChanges(); // in this case dbWord is saved so datetime fields remains intact
        return RedirectToAction("Index", new  idOfCollection = idOfCollection );
    
    return View(word);

【讨论】:

【参考方案5】:

通过在 DateTime 之后添加一个问号使您的属性可以为空。

    public DateTime? SentOn  get; set; 

【讨论】:

以上是关于将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围 - 未使用 DateTime2的主要内容,如果未能解决你的问题,请参考以下文章

将 datetime2 数据类型转换为 datetime 数据错误

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

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

哪一列导致“将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围”?

如何识别列抛出 System.Data.SqlClient.SqlException? (将 datetime2 数据类型转换为 datetime 数据类型)

如何将 sql datetime2 转换为加倍?