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

Cam*_*ron 170 asp.net-mvc

我的HomeController中有以下代码:

public ActionResult Edit(int id)
{
    var ArticleToEdit = (from m in _db.ArticleSet where m.storyId == id select m).First();
    return View(ArticleToEdit);
}

[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Article ArticleToEdit)
{
    var originalArticle = (from m in _db.ArticleSet where m.storyId == ArticleToEdit.storyId select m).First();
    if (!ModelState.IsValid)
        return View(originalArticle);

    _db.ApplyPropertyChanges(originalArticle.EntityKey.EntitySetName, ArticleToEdit);
    _db.SaveChanges();
    return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)

这是Edit方法的视图:

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="headline">Headline</label>
            <%= Html.TextBox("headline") %>
        </p>
        <p>
            <label for="story">Story <span>( HTML Allowed )</span></label>
            <%= Html.TextArea("story") %>
        </p>
        <p>
            <label for="image">Image URL</label>
            <%= Html.TextBox("image") %>
        </p>
        <p>
            <input type="submit" value="Post" />
        </p>
    </fieldset>

<% } %>
Run Code Online (Sandbox Code Playgroud)

当我点击提交按钮时,我收到错误:{"The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated."}任何想法是什么问题?我假设编辑方法正在尝试将DB中的已发布值更新为已编辑的但由于某种原因它不喜欢它...虽然我不明白为什么涉及日期,因为它没有在控制器方法编辑?

Jac*_*cob 164

问题在于您使用ApplyPropertyChanges的模型对象仅填充了表单中的数据(标题,故事和图像). ApplyPropertyChanges将更改应用于对象的所有属性,包括未初始化的DateTime,设置为0001-01-01,这超出了SQL Server的范围DATETIME.

而不是使用ApplyPropertyChanges,我建议检索被修改的对象,更改表单编辑的特定字段,然后使用这些修改保存对象; 这样,只修改了改变的字段.或者,您可以在页面中放置隐藏的输入,并填充其他字段,但对于并发编辑,这将不是非常友好.

更新:

这是一个未经测试的只更新对象的某些字段的示例(假设您使用的是LINQ to SQL):

var story = _db.ArticleSet.First(a => a.storyId == ArticleToEdit.storyId);
story.headline = ArticleToEdit.headline;
story.story = ArticleToEdit.story;
story.image = ArticleToEdit.image;
story.modifiedDate = DateTime.Now;
_db.SubmitChanges();
Run Code Online (Sandbox Code Playgroud)


小智 110

这是人们在使用Entity Framework时遇到的常见错误.当与要保存的表关联的实体具有强制日期时间字段并且您没有使用某个值设置它时,会发生这种情况.

创建的默认日期时间对象的值为,01/01/1000将用于代替null.这将被发送到datetime列,该列可以保存日期值1753-01-01 00:00:00,而不是之前,导致超出范围的异常.

可以通过将数据库字段修改为接受null或通过使用值初始化字段来解决此错误.

  • 当数据库中的datetime字段是可选的并且未设置value时,会发生这种情况.因此,这不是普通人的错误,这是EF架构问题之一. (3认同)

And*_*ich 39

DATETIME支持1753/1/1到"永恒"(9999/12/31),同时 DATETIME2支持0001/1/1到永恒.

MSDN

答: 我想您尝试DateTime使用'0001/1/1'值保存.只需设置断点并调试它,如果是,则替换DateTimenull或设置正常日期.


sky*_*dev 14

这个让我发疯.我想避免使用可以为空的日期时间(DateTime?).我没有选择使用SQL 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;
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 9

您还可以通过添加到模型(实体框架版本> = 5)来解决此问题

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreationDate { get; set; }
Run Code Online (Sandbox Code Playgroud)


小智 7

如果您有一个datetime并且允许为null的列,则会出现此错误.我建议在.SaveChanges()之前设置一个值传递给对象.


Ale*_*nko 5

在我更改模型(代码优先)后出现此错误,如下所示:

public DateTime? DateCreated
Run Code Online (Sandbox Code Playgroud)

public DateTime DateCreated
Run Code Online (Sandbox Code Playgroud)

在 DateCreated 中显示具有空值的行导致此错误。所以我不得不手动使用SQL UPDATE 语句来用标准值初始化字段。

另一种解决方案可能是指定字段的默认值。