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

11

我有一个控制器:

[HttpPost]
public ActionResult Create(Auction auction)
{
    var db = new EbuyDataContext();
    db.Auctions.Add(auction);
    db.SaveChanges();
    return View(auction);
}

一个模型:

public class Auction
{
        public long Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public decimal StartPrice { get; set; }
        public decimal CurrentPrice { get; set; }
        public DateTime StartTime { get; set; }
        public DateTime EndTime { get; set; }}
}

并且有一个视图:

@model Ebuy.Website.Models.Auction
@using (Html.BeginForm())
{
    <p>
        //All the information fields...
        @Html.LabelFor(model => model.EndTime)
        @Html.EditorFor(model => model.EndTime)
    </p>
}

当我尝试运行它时,我收到了以下错误:

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

这个模型-控制器-视图是从一本书上逐字复制的。

我需要输入什么格式到EndTime字段,才能避免这个错误?


你检查过 StartTime 和 EndTime 保存的值了吗? - von v.
10个回答

22

出错的原因是你没有正确地设置这些值,请确保根据你的应用程序区域设置进行设置。例如,对于en-GB,日期格式为dd/mm/yyyy,对于en-US,日期格式为mm/dd/yyyy。

同时,看起来你的数据库已经设置为使用datetime2列,而不是datetime列。

你可以选择:

A)修改数据库,将类型从datetime2改为datetime

B)通过以下方式更改模型中的类型为datetime2

[Column(TypeName = "DateTime2")]
public DateTime StartTime { get; set; }

[Column(TypeName = "DateTime2")]
public DateTime EndTime { get; set; }

我如何修改数据库设置? - Alexandra Orlov
@AlexandraOrlov 如果你的数据库是代码优先的话,那么应用这些属性并重新生成数据库应该没问题。 - Mathew Thompson
我在我的模型中更改了类型,并使用了dd/mm/yyyy版本。我仍然不明白应该如何修改数据库设置,但感谢您的答案。 - Alexandra Orlov
顺便问一下,这可能听起来非常愚蠢,但我在哪里才能访问数据库?我在哪里可以看到EbuyDataContext生成的表格? - Alexandra Orlov
@AlexandraOrlov 哦,那就好了,不需要改变数据库。你应该安装了 SQL Server Express 或正常版?打开 SQL Server Management Studio 并登录到“localhost”,你应该能看到你的数据库。 - Mathew Thompson
明白了,谢谢!我以为应该使用 Visual Studio 自带的 SQL。 - Alexandra Orlov

13

当我试图将未赋值的DateTime成员保存到数据库时,我遇到了相同的问题,使用EntityFramework。 我阅读了这里的答案,学到了可以通过将成员声明为可空来解决此问题。我尝试了一下,它起作用了! 所以,这是一个代码片段,供那些需要的人使用:

public Nullable<DateTime> MyDateTime { get; set; }
或者
public DateTime? MyDateTime { get; set; }

稍后我可以像下面这样使用它:

if(MyDateTime.HasValue)
{
    DoBlaBla(MyDateTime.Value);
}

或者只是像什么都没有发生一样给它赋一个值...

MyDateTime = DateTime.Now;

这对我很有帮助,因为我在我的IdentityUser模型中添加了一个出生日期字段。 - Mikeware

3

您的datetime2数据类型的列是否允许接受null值。如果不允许,则当您没有给这些列赋值时,您可能会遇到此错误。

默认情况下,如果您的模型不使用可空属性,则CodeFirst将生成非可空列。尝试将这些属性转换为可空日期时间。


正如您在模型中所看到的,我没有任何限制。那么datatime2列是什么? - Alexandra Orlov
数据库中的列是datetime2数据类型。抱歉打字错误。你的数据库列是否接受空值? - Amit Rai Sharma
嗯...我不确定。因为我现在正在从书上学习,所以我尝试了“代码优先”版本,创建了一个模型:public class EbuyDataContext : DbContext { public DbSet<Auction> Auctions { get; set; }... - Alexandra Orlov
@AlexandraOrlov:如果你将模型的属性StartTime和EndTime设置为可空DateTime,它应该会解决问题。 - Amit Rai Sharma

0

0

我建议将DateTime属性设置为可空,并使用属性验证确保值在可接受的范围内。

我创建了一个自定义属性,继承自RangeAttribute,用于验证日期值。

public class DbDateRangeAttribute
    : RangeAttribute
{
    public DbDateRangeAttribute()
        : base(typeof(DateTime), SqlDateTime.MinValue.Value.ToShortDateString(), SqlDateTime.MaxValue.Value.ToShortDateString())
    { }
}

然后你就可以像这样使用属性

[DbDateRange]
public DateTime? StartTime { get; set; }

如果用户输入的值超出了 SqlDateTime 的范围(可能是由于客户端日期选择器问题),那么他将会收到一个有意义的错误消息,如下所示:

开始时间字段必须在 1753 年 1 月 1 日 12:00:00 AM 和 9999 年 12 月 31 日 12:00:00 AM 之间。


0
我在处理系统字段(created_on,modified_on)时遇到了这个问题,尽管我的模型被正确定义。
我的问题的原因是使用了disabled属性而不是readonly。表单不会提交已禁用的输入值到控制器,这导致空值,并进而导致最小日期/时间值。
错误:
<div class="form-group">
    @Html.LabelFor(model => model.CreatedOn, htmlAttributes: new { @class = "control-label col-lg-3" })
    <div class="col-lg-9">
        @Html.EditorFor(model => model.CreatedOn, new { htmlAttributes = new { @class = "form-control", disabled="disabled" } })
        @Html.ValidationMessageFor(model => model.CreatedOn, "", new { @class = "text-danger" })
    </div>
</div>

正确:

<div class="form-group">
    @Html.LabelFor(model => model.CreatedOn, htmlAttributes: new { @class = "control-label col-lg-3" })
    <div class="col-lg-9">
        @Html.EditorFor(model => model.CreatedOn, new { htmlAttributes = new { @class = "form-control", @readonly="readonly" } })
        @Html.ValidationMessageFor(model => model.CreatedOn, "", new { @class = "text-danger" })
    </div>
</div>

0

我也遇到了这个问题。

将 datetime2 数据类型转换为 datetime 数据类型会导致超出范围的值 是一个非常不实用的错误。

要解决这个问题,我必须执行以下操作(使用上面的示例):

可以从 -> 工具 -> 库程序包管理器 -> 程序包管理器控制台 中找到程序包管理器控制台。

我在程序包管理器控制台中启用了数据库迁移 -> 启用-迁移。

然后在 Controller 类中添加了以下代码:

public class Auction
{
public long Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public decimal StartPrice { get; set; }
public decimal CurrentPrice { get; set; }

// My Edit to the code Start -->
public Nullable<DateTime> StartTime { get; set; }
public Nullable<DateTime> EndTime { get; set; }}
// My Edit to the code Finish <--
}

然后在模型类中:

[HttpPost]

// My Edit to the code Start -->
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode=true, DataFormatString = "{0:d}")]]
// My Edit to the code Finish <--

public ActionResult Create(Auction auction)
{

// My Edit to the code Start -->
if(ModelState.IsValid)
{
// Only Apply the DateTime if the Action is Valid...
auction.StartTime = DateTime.Now;
}
// My Edit to the code Finish <--

var db = new EbuyDataContext();
db.Auctions.Add(auction);
db.SaveChanges();
return View(auction);
}

然后在程序包管理器控制台中将更改添加到数据库 -> Add-Migration(在此处添加您的更改)

然后在程序包管理器控制台中运行数据库更新 -> Update-Database

重要的是要注意,在上述实现中,数据库看到的数据是正确的:

E.G: 17/06/2013 12:00:00 AM

这个错误非常愚蠢,但似乎已经困扰了很多人,包括我自己。现在我知道为什么会出现这个错误,看起来很容易解决和避免,但为什么这样一个常见的问题在最新版本的MVC中没有被修复,超出了我的理解。


0

我在数据库中的DateCreated上设置了默认的getdate()值。因为我认为不需要在EF中设置该值,所以我没有设置它。但是一旦我通过EF在插入时传递了该值,错误就消失了。为什么会出现这种错误呢?我从未弄清楚。


0

当我在服务层尝试将change_date添加到我的联系人实体时,我遇到了类似的错误。通过从控制器添加参数解决了这个问题。请尝试从控制器添加参数。


0
有点晚了,这个错误让我苦恼了几个小时。有一天我的代码在本地主机上停止工作了,但是在UAT服务器上的应用程序却没有问题。由于我使用的是公司网络,我追踪到是Windows更新将我的日期区域设置从yyyy/mm/dd更改为dd/mm/yyyy(我正在写入SQL)。
再次检查您的区域设置是否有任何更改。
搜索->设置区域格式->其他日期、时间和区域设置,更新为正确的格式。

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