Konwersja typu danych datetime2 na typ danych datetime spowodowała uzyskanie wartości spoza zakresu

174

Mam następujący kod w moim 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");
}

A oto widok dla metody 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>

<% } %>

Po naciśnięciu przycisku przesyłania {"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."}pojawia się błąd: Jakieś pomysły na czym polega problem? Zakładam, że metoda edycji próbuje zaktualizować wartość opublikowaną w bazie danych do edytowanej w dniu, ale z jakiegoś powodu jej się to nie podoba ... Chociaż nie rozumiem, dlaczego chodzi o datę, ponieważ nie jest wspomniana w metoda kontrolera do edycji?

Cameron
źródło
1
modelBuilder.Entity<WorldInfo>().Property(d => d.CurrentTime).HasColumnType("datetime2");
Anthony Nichols,

Odpowiedzi:

166

Problem polega na tym, że używasz ApplyPropertyChangesz obiektem modelu, który został wypełniony tylko danymi w formularzu (nagłówek, artykuł i obraz). ApplyPropertyChangesstosuje zmiany do wszystkich właściwości obiektu, w tym niezainicjowanego obiektu DateTime, który jest ustawiony na 0001-01-01, który jest poza zakresem SQL Server DATETIME.

Zamiast używać ApplyPropertyChanges, sugerowałbym pobranie modyfikowanego obiektu, zmianę określonych pól edytowanych przez formularz, a następnie zapisanie obiektu z tymi modyfikacjami; w ten sposób modyfikowane są tylko zmienione pola. Alternatywnie możesz umieścić ukryte dane wejściowe na swojej stronie z wypełnionymi innymi polami, ale nie byłoby to zbyt przyjazne przy jednoczesnych edycjach.

Aktualizacja:

Oto nieprzetestowany przykład aktualizacji niektórych pól obiektu (przy założeniu, że używasz 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();
Jakub
źródło
Bardzo pomocny :) Zastanawiałem się, dlaczego zmienia się data, skoro jej nie sprecyzowałem. Czy możesz pomóc zmienić metodę Edit, aby nie korzystała już z ApplyPropertyChanges? Ponieważ jestem nowy w ASP.NET i nie rozumiem tego wszystkiego w tej chwili. Dzięki kolego.
Cameron,
A co gdybym chciał ustawić datę na aktualną tj. data i godzina aktualizacji artykułu? Ponieważ prawdopodobnie będzie to najlepsza opcja i przypuszczam, że działałaby ze zmianami ApplyPropertyChanges, które mam w grze.
Cameron,
Zobacz moją edycję (zakłada, że modifiedDatetak nazywa się Twoja nieruchomość)
Jakub
SubmitChanges nie działa w mojej aplikacji: / czy można dodać ten story.modifiedDate = DateTime.Now;bit do mojego obecnego kodu? Dzięki
Cameron
1
ten błąd występuje, gdy ustawimy public DateTime CreatedDate zamiast public DateTime? CreatedDate, ponieważ DateTime nie może być null, więc dlaczego jego błąd dawania poza zakresem. może to pomóc, ale rozwiązało mój problem.
adnan
115

Jest to typowy błąd, z którym spotykają się ludzie podczas korzystania z Entity Framework. Dzieje się tak, gdy encja skojarzona z zapisywaną tabelą ma obowiązkowe pole daty i godziny i nie ustawisz dla niego jakiejś wartości.

Domyślny obiekt datetime jest tworzony z wartością 01/01/1000i będzie używany zamiast null. Zostanie to przesłane do kolumny datetime, w której mogą znajdować się wartości dat 1753-01-01 00:00:00począwszy od , ale nie wcześniej, co prowadzi do wyjątku poza zakresem.

Ten błąd można rozwiązać, modyfikując pole bazy danych, aby akceptowało wartość null, lub inicjując pole wartością.

Sanjay Kumar Madhva
źródło
3
Dzieje się tak, gdy pole daty i godziny w bazie danych jest opcjonalne, a wartość nie jest ustawiona. Dlatego nie jest to typowy błąd ludzi, jest to jeden z problemów architektonicznych EF.
GSoft Consulting
1
Zgadzam się, że EF powinien zobaczyć typ w DB i odpowiednio dostosować lub rzucić lub przynajmniej zgłosić dokładniejszy błąd. Z drugiej strony podoba mi się twoja odpowiedź, ponieważ podałeś 2 opcje zamiast zwykłej - zainicjuj pole wartością minimalną.
DanteTheSmith
43

DATETIMEobsługuje 1753/1/1 do „wieczności” (9999/12/31), podczas gdy DATETIME2obsługuje 0001/1/1 do wieczności.

Msdn

Odpowiedź: Przypuszczam, że próbujesz zapisać DateTimez wartością „0001/1/1”. Wystarczy ustawić punkt przerwania i debugowania to, jeśli tak to wymienić DateTimez nulllub zestaw normalny termin.

Andrew Orsich
źródło
Co jednak umieszczam w kontrolerze? Debugowanie powoduje po prostu ten błąd, który zamieściłem powyżej. Dzięki.
Cameron,
wydaje się błąd tutaj -> _db.SaveChanges (); Możesz ustawić punkt przerwania przed tą linią ...
Andrew Orsich
Tak, zrobił. Następnie mówi, że ich jest błąd w SaveChanges, więc patrzę na InnerException i mówi, że to z powodu opublikowanego błędu, więc to jest błąd!
Cameron,
Czy sprawdziłeś wartość DateTime przed _db.SaveChanges (); został wezwany? Powinien być świetny niż „1753/1/1”.
Andrew Orsich,
Oryginalna wartość daty artykułu to {18/10/2009 00:00:00}, a wartość daty w artykule ArticleToEdit to {01/01/0001 00:00:00}, więc wygląda na to, że próbuje zmienić datę na pierwszą z wszystkiego, co nie jest Nie chcę, ale nie wyjaśnia, dlaczego zgłasza błąd, ponieważ format jest taki sam, prawda?
Cameron,
14

Ten doprowadzał mnie do szału. Chciałem uniknąć używania daty i godziny zerowej ( DateTime?). Nie miałem również możliwości użycia typu datetime2 SQL 2008 ( modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2");).

Ostatecznie zdecydowałem się na:

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;
                    }
                }
            }
        }
    }
}
sky-dev
źródło
10

Możesz również rozwiązać ten problem, dodając do modelu (wersja Entity Framework> = 5)

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreationDate { get; set; }
Dongolo Jeno
źródło
8

Jeśli masz kolumnę z datą i godziną i dopuszcza wartość null, zostanie wyświetlony ten błąd. Zalecam ustawienie wartości do przekazania do obiektu przed .SaveChanges ();

Patrick
źródło
5

Otrzymałem ten błąd po zmianie modelu (najpierw kod) w następujący sposób:

public DateTime? DateCreated

do

public DateTime DateCreated

Obecne wiersze z wartością null w DateCreated spowodowały ten błąd. Musiałem więc ręcznie użyć instrukcji SQL UPDATE do inicjalizacji pola ze standardową wartością.

Innym rozwiązaniem mogłoby być określenie domyślnej wartości pola.

Aleksandr Khomenko
źródło
3

W moim przypadku w inicjatorze z klasy, której używałem w tabeli bazy danych, nie ustawiałem żadnej wartości domyślnej na moją właściwość DateTime, co spowodowało problem wyjaśniony w odpowiedzi @Andrew Orsich. Dlatego właśnie ustawiłem właściwość na wartość null. Mogłem też podać mu DateTime.Now w konstruktorze. Mam nadzieję, że to komuś pomoże.

StinkyCat
źródło
3

Wygląda na to, że używasz struktury encji. Moje rozwiązanie polegało na przełączeniu wszystkich kolumn z datą i godziną na datetime2 i użyciu datetime2 dla wszystkich nowych kolumn, innymi słowy, aby EF domyślnie używał datetime2. Dodaj to do metody OnModelCreating w swoim kontekście:

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

To dostanie wszystkie DateTime i DateTime? właściwości wszystkich elementów w modelu.

Ogglas
źródło
2

Miałem ten sam problem, niestety mam dwie właściwości DateTime w moim modelu i jedna właściwość DateTime ma wartość null, zanim wykonam SaveChanges.

Dlatego upewnij się, że model ma wartość DateTime przed zapisaniem zmian lub ustaw wartość null, aby zapobiec błędom:

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

Więc to rozwiązuje mój problem, jest to kwestia upewnienia się, że data twojego modelu jest poprawna przed utrwaleniem w bazie danych:

public DateTime DateAdded { get; set; }
public DateTime? ReleaseDate { get; set; }
Willy David Jr
źródło
2

Jeśli używasz Entity Framework w wersji> = 5, zastosowanie adnotacji [DatabaseGenerated (DatabaseGeneratedOption.Computed)] do właściwości DateTime klasy umożliwi wyzwalaczowi tabeli bazy danych wykonywanie zadania polegającego na wprowadzaniu dat tworzenia rekordów i aktualizowaniu rekordów bez powodowania Twój kod Entity Framework do gagowania.

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

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

Jest to podobne do odpowiedzi szóstej, napisanej przez Dongolo Jeno i zredagowanej przez Gille Q.

Jim Kay
źródło
1

Ponadto, jeśli nie znasz części kodu, w której wystąpił błąd, możesz profilować „złe” wykonanie sql za pomocą profilera sql zintegrowanego z mssql.

Zły parametr daty i godziny wyświetli coś takiego:

zły parametr

Nigrimmist
źródło
1

Ten problem zwykle występuje, gdy próbujesz zaktualizować jednostkę. Na przykład masz podmiot, który zawiera pole o nazwie DateCreated, która jest [Wymagane] i po wstawieniu rekordu, nie jest zwracany błąd ale gdy chcesz zaktualizować ten konkretny podmiot, Ci uzyskać

błąd konwersji datetime2 poza zakresem.

Oto rozwiązanie:

W widoku edycji, tj. edit.cshtmlDla użytkowników MVC, wszystko, co musisz zrobić, to dodać ukryte pole formularza DateCreatedtuż poniżej ukrytego pola dla klucza podstawowego danych edycji.

Przykład:

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

Dodając to do widoku edycji, nigdy nie będziesz mieć tego błędu, zapewniam cię.

Aduwu Joseph
źródło
1

Musisz włączyć wartość null dla swojej zmiennej daty:

 public Nullable<DateTime> MyDate{ get; set; }
Badr Bellaj
źródło
0

Spróbuj ustawić wartość null dla swojej właściwości.

    public DateTime? Time{ get; set; }

Pracował dla mnie.

typhon04
źródło
0

Jeśli masz dostęp do bazy danych, możesz zmienić typ kolumny bazy danych z datetime na datetime2 (7), to nadal wyśle ​​obiekt datetime i zostanie on zapisany

Sergiu Mindras
źródło
0

Model powinien mieć datęetime dopuszczającą wartość null. Zamiast metody ApplyPropertyChanges należy użyć wcześniej sugerowanej metody pobierania obiektu, który ma zostać zmodyfikowany. W moim przypadku miałem tę metodę, aby zapisać mój obiekt:

public ActionResult Save(QCFeedbackViewModel item)

A potem w serwisie pobieram za pomocą:

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

Pełny kod usługi jest następujący:

 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();
anu
źródło
0

[Rozwiązany] W Entity Framework Code First (mój przypadek) po prostu zmienia się, DateTimeaby DateTime?rozwiązać mój problem.

/*from*/ public DateTime SubmitDate { get; set; }
/*to  */ public DateTime? SubmitDate { get; set; }
Amir Astaneh
źródło
0

Błąd: konwersja typu danych datetime2 na typ danych datetime spowodowała wystąpienie wartości spoza zakresu.

Ten błąd wystąpił, gdy z powodu NIE przypisano żadnej wartości w kolumnie daty NOT NULL w bazie danych SQL przy użyciu EF i został rozwiązany przez przypisanie tego samego.

Mam nadzieję że to pomoże!

user2964808
źródło
0

Mam ten problem podczas tworzenia moich klas z podejścia Database First. Rozwiązany przy użyciu prostego Convert.DateTime (dateCausingProblem) W rzeczywistości zawsze staraj się konwertować wartości przed przekazaniem, oszczędza to przed nieoczekiwanymi wartościami.

Ansar nisar Gill
źródło
0

musisz dopasować format wejściowy swojego pola daty do wymaganego formatu jednostki, czyli rrrr / mm / dd

marc
źródło
1
Istnieją inne odpowiedzi, które zawierają pytanie OP i zostały opublikowane jakiś czas temu. Publikując odpowiedź, zobacz: Jak napisać dobrą odpowiedź? , upewnij się, że dodałeś nowe rozwiązanie lub znacznie lepsze wyjaśnienie, szczególnie w przypadku odpowiedzi na starsze pytania.
help-info.de