Преобразование типа данных datetime2 в тип данных datetime привело к значению вне допустимого диапазона - PullRequest
164 голосов
/ 05 января 2011

В моем 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");

    }

И это представление для метода редактирования:

<% 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>

<% } %>

Когда я нажимаю кнопку отправки, я получаю сообщение об ошибке: {"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."} Есть идеи, в чем проблема? Я предполагаю, что метод edit пытается обновить опубликованное значение в БД до отредактированного, но по какой-то причине это не нравится ... Хотя я не понимаю, почему используется дата, так как она не упоминается в метод контроллера для редактирования?

Ответы [ 20 ]

159 голосов
/ 06 января 2011

Проблема в том, что вы используете ApplyPropertyChanges с объектом модели, который был заполнен только данными в форме (заголовок, история и изображение). ApplyPropertyChanges применяет изменения ко всем свойствам объекта, включая неинициализированный DateTime, для которого установлено значение 0001-01-01, что находится за пределами диапазона DATETIME.

для SQL Server.

Вместо того, чтобы использовать 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();
110 голосов
/ 12 июля 2012

Это распространенная ошибка, с которой люди сталкиваются при использовании Entity Framework. Это происходит, когда объект, связанный с сохраняемой таблицей, имеет обязательное поле даты и времени, и вы не устанавливаете его с каким-либо значением.

Объект даты и времени по умолчанию создается со значением 01/01/1000 и будет использоваться вместо нуля. Это будет отправлено в столбец datetime, который может содержать значения даты от 1753-01-01 00:00:00 и далее, но не раньше, что приведет к исключению вне диапазона.

Эта ошибка может быть исправлена ​​путем изменения поля базы данных для принятия значения NULL или путем инициализации поля со значением.

37 голосов
/ 06 января 2011

DATETIME поддерживает 1753/1/1 до "вечности" (9999/12/31), в то время как DATETIME2 поддерживает 0001/1/1 до вечности.

Msdn

Ответ: Я полагаю, вы пытаетесь сохранить DateTime со значением '0001/1/1'.Просто установите точку останова и отладьте ее, если так, то замените DateTime на null или установите нормальную дату.

14 голосов
/ 02 июля 2012

Этот сводил меня с ума. Я хотел избежать использования обнуляемого времени даты (DateTime?). У меня также не было возможности использовать тип datetime2 в SQL 2008 (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;
                    }
                }
            }
        }
    }
}
9 голосов
/ 30 января 2017

Эту проблему также можно исправить, добавив в модель (версия Entity Framework> = 5)

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreationDate { get; set; }
7 голосов
/ 26 января 2011

Если у вас есть столбец с датой и разрешением null, вы получите эту ошибку. Я рекомендую установить значение для передачи объекту до .SaveChanges ();

4 голосов
/ 28 января 2016

Я получил эту ошибку после того, как изменил модель (сначала код) следующим образом:

public DateTime? DateCreated

до

public DateTime DateCreated

Причиной этой ошибки стали строки с нулевым значением в DateCreated. Поэтому мне пришлось использовать SQL UPDATE Statement вручную для инициализации поля стандартным значением.

Другим решением может быть указание значения по умолчанию для поля.

3 голосов
/ 29 августа 2016

Похоже, вы используете сущность Framework. Мое решение состояло в том, чтобы переключить все столбцы datetime на datetime2 и использовать datetime2 для любых новых столбцов, другими словами, EF по умолчанию использует datetime2. Добавьте это к методу OnModelCreating в вашем контексте:

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

Что получит все DateTime и DateTime? свойства всех объектов вашей модели.

3 голосов
/ 11 июля 2014

В моем случае в инициализаторе из класса, который я использовал в таблице базы данных, я не устанавливал никакого значения по умолчанию для своего свойства DateTime, поэтому возникла проблема, объясненная в ответе @Andrew Orsich. Так что я просто сделал собственность обнуляемой. Или я мог бы также дать ему DateTime.Now в конструкторе. Надеюсь, это кому-нибудь поможет.

2 голосов
/ 27 апреля 2018

Если вы используете Entity Framework версии> = 5, тогда применение аннотации [DatabaseGenerated (DatabaseGeneratedOption.Computed)] к вашим свойствам DateTime вашего класса позволит триггеру таблицы базы данных выполнять свою работу по вводу дат для создания записи и записиобновление, не вызывая зависания кода Entity Framework.

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateCreated { get; set; }

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateUpdated { get; set; }

Это похоже на 6-й ответ, написанный Донголо Джено и отредактированный Жилле Q.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...