Преобразование типа данных datetime2 в тип данных datetime привело к значению вне допустимого диапазона

174

У меня есть следующий код в моем 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");
}

И это представление для метода 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>

<% } %>

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

Cameron
источник
1
modelBuilder.Entity<WorldInfo>().Property(d => d.CurrentTime).HasColumnType("datetime2");
Энтони Николс

Ответы:

166

Проблема заключается в том, что вы используете 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();
Иаков
источник
Очень полезно :) Мне было интересно, почему дата менялась, когда я не указал ее. Можете ли вы помочь изменить метод редактирования, чтобы он больше не использовал ApplyPropertyChanges? Поскольку я новичок в ASP.NET и до конца не понимаю всего этого. Спасибо приятель
Кэмерон
Что делать, если я хотел установить дату на текущую дату, т.е. дата и время, когда статья была обновлена? Поскольку это, вероятно, будет лучшим вариантом, и я предполагаю, что он будет работать с ApplyPropertyChanges, которые у меня в игре.
Кэмерон
Смотрите мое редактирование (предполагается, что modifiedDateэто название вашей собственности)
Джейкоб
SubmitChanges не работает в моем приложении: / возможно ли добавить story.modifiedDate = DateTime.Now;бит в мой текущий код? Спасибо
Кэмерон
1
эта ошибка возникает, когда мы устанавливаем публичный DateTime CreatedDate вместо публичного DateTime? CreatedDate, потому что DateTime не может быть нулевым, так почему его выдают за пределы допустимой ошибки. это может помочь, но это решило мою проблему.
Аднан
115

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

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

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

Санджай Кумар Мадхва
источник
3
Это происходит, когда поле datetime в базе данных является необязательным и значение не задано. Поэтому это не обычная ошибка людей, это одна из архитектурных проблем EF.
GSoft Consulting 13.09.15
1
Я согласен с тем, что EF должен видеть тип в БД и корректировать его соответствующим образом или выдавать или, по крайней мере, выдавать более точную ошибку. С другой стороны, мне нравится ваш ответ, так как вы предоставили 2 варианта вместо обычного - инициализируйте поле с минимальным значением.
DanteTheSmith
43

DATETIMEподдерживает 1753/1/1 в «вечность» (9999/12/31), а DATETIME2поддерживает 0001/1/1 в вечность.

MSDN

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

Андрей Орсич
источник
Что я помещаю в контроллер, хотя? Отладка только поднимает ту ошибку, которую я отправил выше. Спасибо.
Кэмерон
Кажется, здесь ошибка -> _db.SaveChanges (); Вы можете установить
точку
Да, сделал. Затем он говорит, что это ошибка SaveChanges, поэтому я смотрю на InnerException, и он говорит, что это из-за опубликованной ошибки, так что это ошибка!
Кэмерон
Вы проверяли значение DateTime перед _db.SaveChanges (); назывался? Это должно быть здорово, чем «1753/1/1».
Андрей Орсич
Значение даты originalArticle - {18/10/2009 00:00:00}, а значение даты ArticleToEdit - {01/01/0001 00:00:00}, поэтому кажется, что он пытается изменить дату на 1-е из всего, что не не хочу, я хочу, но не объясняю, почему выдает ошибку, поскольку формат такой же правильный?
Кэмерон
14

Этот сводил меня с ума. Я хотел избежать использования обнуляемой даты ( 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;
                    }
                }
            }
        }
    }
}
небесно-DEV
источник
10

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

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreationDate { get; set; }
Донголо Джено
источник
8

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

Патрик
источник
5

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

public DateTime? DateCreated

в

public DateTime DateCreated

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

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

Александр Хоменко
источник
3

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

StinkyCat
источник
3

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

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

Что получит все DateTime и DateTime? свойства на всех сущностях в вашей модели.

Ogglas
источник
2

У меня была та же проблема, к сожалению, у меня есть два свойства DateTime в моей модели, и одно свойство DateTime является нулевым, прежде чем я сделаю SaveChanges.

Поэтому убедитесь, что ваша модель имеет значение DateTime, прежде чем сохранять изменения, или сделайте его обнуляемым, чтобы избежать ошибки:

public DateTime DateAdded { get; set; }   //This DateTime always has a value before persisting to the database.
public DateTime ReleaseDate { get; set; }  //I forgot that this property doesn't have to have DateTime, so it will trigger an error

Таким образом, это решает мою проблему, поэтому необходимо убедиться, что дата вашей модели верна перед сохранением в базе данных:

public DateTime DateAdded { get; set; }
public DateTime? ReleaseDate { get; set; }
Вилли Дэвид младший
источник
2

Если вы используете 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-й ответ, написанный Донголо Джено и отредактированный Гилле В.

Джим Кей
источник
1

Кроме того, если вы не знаете часть кода, где произошла ошибка, вы можете профилировать «плохое» выполнение SQL Server, используя SQL Server Profiler, интегрированный в MSSQL.

Плохой параметр datetime будет отображать что-то вроде этого:

плохой парам

Nigrimmist
источник
1

Эта проблема обычно возникает, когда вы пытаетесь обновить сущность. Например у вас есть объект , который содержит поле с именем , DateCreatedкоторое [необходимо] и при вставке записи, не возвращается никакой ошибки , но если вы хотите обновить этот конкретный объект, Вам получить

преобразование datetime2 вне диапазона.

Теперь вот решение:

В представлении редактирования, т. edit.cshtmlЕ. Для пользователей MVC, все, что вам нужно сделать, это добавить скрытое поле формы для вашего DateCreatedчуть ниже скрытого поля для первичного ключа данных редактирования.

Пример:

@Html.HiddenFor(model => model.DateCreated)

Добавив это к вашему редактируемому виду, у вас никогда не будет этой ошибки, я вас уверяю.

Адуу Джозеф
источник
1

Вы должны включить нулевое значение для вашей переменной даты:

 public Nullable<DateTime> MyDate{ get; set; }
Бадр Беллай
источник
0

Попробуйте сделать вашу собственность обнуляемой.

    public DateTime? Time{ get; set; }

Работал на меня.

typhon04
источник
0

Если у вас есть доступ к БД, вы можете изменить тип столбца БД с datetime на datetime2 (7), он все равно отправит объект datetime, и он будет сохранен

Серджиу Миндрас
источник
0

Модель должна иметь значение даты и времени, обнуляемое. Предложенный ранее метод получения объекта, который необходимо изменить, следует использовать вместо ApplyPropertyChanges. В моем случае у меня был этот метод для сохранения моего объекта:

public ActionResult Save(QCFeedbackViewModel item)

И затем в сервисе, я получаю с помощью:

RETURNED = item.RETURNED.HasValue ? Convert.ToDateTime(item.RETURNED) : (DateTime?)null 

Полный код обслуживания приведен ниже:

 var add = new QC_LOG_FEEDBACK()
            {

                QCLOG_ID = item.QCLOG_ID,
                PRE_QC_FEEDBACK = item.PRE_QC_FEEDBACK,
                RETURNED = item.RETURNED.HasValue ? Convert.ToDateTime(item.RETURNED) : (DateTime?)null,
                PRE_QC_RETURN = item.PRE_QC_RETURN.HasValue ? Convert.ToDateTime(item.PRE_QC_RETURN) : (DateTime?)null,
                FEEDBACK_APPROVED = item.FEEDBACK_APPROVED,
                QC_COMMENTS = item.QC_COMMENTS,
                FEEDBACK = item.FEEDBACK
            };

            _context.QC_LOG_FEEDBACK.Add(add);
            _context.SaveChanges();
ана
источник
0

[Решено] В Entity Framework Code First (мой случай) просто меняется, DateTimeчтобы DateTime?решить мою проблему.

/*from*/ public DateTime SubmitDate { get; set; }
/*to  */ public DateTime? SubmitDate { get; set; }
Амир Астанех
источник
0

Ошибка: преобразование типа данных datetime2 в тип данных datetime привело к значению вне допустимого диапазона.

Эта ошибка произошла, когда из-за НЕ назначено какое-либо значение столбцу даты NOT NULL в БД SQL с помощью EF, и была устранена путем присвоения того же значения.

Надеюсь это поможет!

user2964808
источник
0

Получил эту проблему, когда создал мои классы из подхода Database First. Решено с помощью простого Convert.DateTime (dateCausingProblem) На самом деле, всегда пытайтесь преобразовать значения перед передачей, это спасает вас от неожиданных значений.

Ансар Нисар Джилл
источник
0

Вы должны сопоставить формат ввода вашего поля даты с требуемым форматом объекта, который является гггг / мм / дд

Марк
источник
1
Есть другие ответы, которые предоставляют вопрос ОП, и они были опубликованы некоторое время назад. При публикации ответа смотрите: Как мне написать хороший ответ? Пожалуйста, убедитесь, что вы добавили либо новое решение, либо существенно лучшее объяснение, особенно когда отвечаете на старые вопросы.
help-info.de