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

3

将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。


在调用 SaveChanges() 之前,LastReviewedNextReview 的实际值是什么? - haim770
数据库中有一些日期时间字段是可空的吗? - azhar_SE_nextbridge
@azhar_SE_nextbridge:不,这些字段都不可为空。 - Piotrek
也许你的一个或多个 DateTime 值超出了 SQL DATETIME 变量的范围(例如:如果它具有其默认值 DateTime.MinValue)。尝试使用调试器逐步执行并检查 LastReviewed / NextReview 的值。 - Joe
5个回答

2
DateTime对象在未明确设置值时默认为DateTime.MinValue。
所以,您的模型中存在一个DateTime对象没有被设置并默认使用此值。如上所述,此值超出了DateTime dbtype的范围,因此EntityFramework将其转换为DateTime2 dbtype,这会导致数据库中的类型转换错误。
要解决此问题,请检查模型中的所有DateTime对象,并确保它们都设置为DateTime.MinValue之外的其他任何值。如果您不想将值设置为任何值,则在db和model中都使该字段可为空,就可以使所有东西正常工作了。
请注意,设置db列的默认值无法解决此问题,转换发生得太早,必须明确设置值。

1
  • DateTime 范围:1753年1月1日 - 9999年12月31日

  • DateTime2 范围:0001年1月1日 - 9999年12月31日

为避免冲突,请使用以下代码。

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

为什么我必须用这种奇怪的方式来做?我不能在创建变量时声明吗?就像“public DateTime2 LastReviewed { get; set; }”一样? - Piotrek
在您的DBContext类中。https://msdn.microsoft.com/zh-cn/library/system.data.entity.dbcontext.onmodelcreating(v=vs.113).aspx - Ilya Sulimanov

0

如果你不想改变日期时间字段(和其他你不想修改的字段)的旧值,就需要保留它们。为此,从数据库中检索旧实体,并仅更改在编辑表单中更新的字段。例如:

[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);
}

0

如果要使日期时间可空,你需要显式地强制它们。例如,如果属性“LastReviewed”是可空的,你应该像下面这样声明它。

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

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


但我不想将其设为可为空。我需要它被设置,这是这里最重要的变量之一。 - Piotrek
默认情况下,如果您想为该日期时间对象分配值,则会将最小值分配给它。但是,如果您分配了值但未正确映射,则会发生此错误... - azhar_SE_nextbridge

0

在 DateTime 后面加上问号,使您的属性可为空。

    public DateTime? SentOn { get; set; }

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