Перетворення типу даних 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");
}

Ось такий спосіб редагування:

<% 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."}якісь ідеї в чому проблема Я припускаю, що метод редагування намагається оновити розміщене значення в БД до відредагованого, але чомусь це не сподобалось ... Хоча я не бачу, чому ця дата задіяна, оскільки вона не згадується в метод контролера для редагування?


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

Відповіді:


166

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

Замість того, щоб використовувати ApplyPropertyChanges, я пропоную отримати об'єкт, який буде змінено, змінити конкретні поля, які редагує форма, а потім зберегти об'єкт цими модифікаціями; таким чином, змінюються лише змінені поля. Крім того, ви можете розміщувати на своїй сторінці приховані вкладиші з іншими заповненими полями, але це не буде дуже дружньо з одночасними правками.

Оновлення:

Ось неперевірений зразок просто оновлення деяких полів вашого об’єкта (це передбачається, що ви використовуєте LINQ до 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();

Дуже корисно :) Мені було цікаво, чому дата змінювалася, коли я її не вказував. Чи можете ви допомогти змінити метод Edit тоді, щоб він більше не використовував ApplyPropertyChanges? Оскільки я новачок у ASP.NET і наразі не все це розумію. Дякую приятелю.
Камерон

Що робити, якщо я хотів встановити дату на поточну дату, тобто. дата оновлення статті? Оскільки це, мабуть, буде найкращим варіантом, і я припускаю, що він буде працювати з ApplyPropertyChanges, який я маю в грі.
Камерон

Дивіться мою редакцію (передбачається, що modifiedDateце назва вашої власності)
Яків

SubmitChanges не працює в моєму додатку: / чи можна додати story.modifiedDate = DateTime.Now;біт до мого поточного коду? Спасибі
Камерон

1
ця помилка виникає, коли ми встановлюємо загальнодоступні DateTime CreatedDate замість загальнодоступних DateTime? CreatedDate, тому що DateTime не може бути нульовим, тому чому його видає помилку з діапазону. це може бути корисним, але це вирішило мою проблему.
аднан

115

Це поширена помилка, з якою люди стикаються під час використання Entity Framework. Це відбувається, коли об'єкт, пов'язаний із збереженою таблицею, має обов'язкове поле для дати, і ви не встановите його з деяким значенням.

Об'єкт datetime за замовчуванням створюється зі значенням 01/01/1000та буде використовуватися замість null. Це буде надіслано до стовпця "Час дати", який може містити значення дати 1753-01-01 00:00:00віднизу, але не раніше, що призводить до виключення поза діапазоном.

Цю помилку можна усунути, змінивши поле бази даних, щоб прийняти null, або ініціалізуючи поле зі значенням.


3
Це відбувається, коли поле дати в базі даних необов’язкове і значення не встановлено. Тому це не звичайна помилка людей, це одна з архітектурних проблем EF.
GSoft Consulting

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".
Андрій Орсич

Початкове значення дати статті - {18/10/2009 00:00:00}, а значення дати DateToEdit - {01/01/0001 00:00:00}, тому, схоже, воно намагається змінити дату на першу частину всього, що не є Я не хочу, але хочу, але не пояснює, чому він видає помилку, оскільки формат той самий прав?
Камерон

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

10

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

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

8

Якщо у вас стовпець, який є датою і дозволяє нулю, ви отримаєте цю помилку. Я рекомендую встановити значення для передачі об'єкту раніше .SaveChanges ();


5

Я отримав цю помилку після того, як я змінив модель (код спочатку) наступним чином:

public DateTime? DateCreated

до

public DateTime DateCreated

Присутні рядки з нульовим значенням у DateCreate спричинили цю помилку. Тому мені довелося використовувати оператор оновлення SQL вручну для ініціалізації поля зі стандартним значенням.

Іншим рішенням може бути визначення значення за замовчуванням для поданого.


3

У моєму випадку в ініціалізаторі класу, який я використовував у таблиці бази даних, я не встановлював жодного значення за замовчуванням для свого властивості DateTime, тому в результаті проблема пояснюється у відповіді @Andrew Orsich. Тому я просто зробив майно непридатним. Або я також міг би дати це DateTime.Now у конструкторі. Сподіваюся, це комусь допоможе.


3

Схоже, ви використовуєте структуру сутності. Моє рішення полягала в тому, щоб переключити всі стовпці дати на дату2 і використовувати дату2 для будь-яких нових стовпців, іншими словами зробити EF використовувати datetime2 за замовчуванням. Додайте це до методу OnModelCreating у вашому контексті:

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

Це отримає всі DateTime та DateTime? властивості для всіх об'єктів вашої моделі.


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-ту відповідь, написану Донголо Джоно та за редакцією Гілле Q.


1

Крім того, якщо ви не знаєте частину коду, де сталася помилка, ви можете профілювати виконання «поганого» sql, використовуючи sql-профілер, інтегрований у mssql.

Неправильний параметр дати побачить щось таке:

поганий парам


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

Працювали для мене.


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 Спочатку (мій випадок) просто змінюється, DateTimeщоб DateTime?вирішити мою проблему.

/*from*/ public DateTime SubmitDate { get; set; }
/*to  */ public DateTime? SubmitDate { get; set; }

0

Помилка: перетворення типу даних datetime2 у тип даних datetime призвело до значення поза діапазоном.

Ця помилка сталася через NOT присвоїли жодне значення стовпцю дати NOT NULL у SQL DB за допомогою EF, і було усунено шляхом призначення того самого.

Сподіваюся, це допомагає!


0

Зробив цю проблему під час створення моїх класів із підходу Database First. Вирішено за допомогою просто Convert.DateTime (dateCausingProblem) Насправді завжди намагайтеся перетворити значення перед передачею, це позбавить вас від несподіваних значень.


0

ви повинні відповідати вхідному формату поля вашої дати до потрібного формату сутності, який становить рр / г / дд


1
Є й інші відповіді, які забезпечують питання ОП, і вони були опубліковані деякий час тому. Опублікувавши відповідь, дивіться: Як написати гарну відповідь? , переконайтеся, що ви додали або нове рішення, або істотно краще пояснення, особливо, відповідаючи на старі питання.
help-info.de
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.