Błąd - przepełnienie SqlDateTime. Musi być między 01.01.1753 00:00 a 31.12.19999 11:59:59

82

Używałem tego fragmentu kodu, który napisałem i działa on w ten najbardziej niejasny sposób. Chcę wstawić wiersz do bazy danych, który zawiera dwie kolumny DateTime:

myrow.ApprovalDate = DateTime.Now
myrow.ProposedDate = DateTime.Now

A jednak kiedy aktualizuję bazę danych otrzymuję taki błąd:

Przepełnienie SqlDateTime. Musi być między 01.01.1753 00:00 a 31.12.19999 11:59:59.

Próbowałem nawet skopiować wstawioną wartość z bazy danych i zakodować ją na stałe w aktualizowanym obiekcie:

// I copied this value from the DB
myrow.ApprovalDate =  Convert.ToDateTime("2008-12-24 00:00:00.000");

Wciąż ten sam błąd, dziwna część polega na tym, że powyższa sztuczka zadziałała dla pierwszego wstawienia do bazy danych, ale od tego momentu zawiodła. Jakieś pomysły, co się dzieje?

Drew Noakes
źródło
Prześlij swój kod. Możesz również rozważyć po prostu sprawdzenie, co linq buduje pod kołdrą.
NotMe

Odpowiedzi:

87

A DateTimew C # jest typem wartości, a nie typem referencyjnym, w związku z czym nie może mieć wartości null. Może to być jednak stała, DateTime.MinValuektóra jest poza zakresem DATETIMEtypu danych Sql Servers .

Typy wartości zawsze mają (domyślną) wartość (zero) bez konieczności ich jawnego ustawiania (w tym przypadku DateTime.MinValue).

Wniosek jest taki, że prawdopodobnie masz nieustawioną wartość DateTime, którą próbujesz przekazać do bazy danych.

DateTime.MinValue = 1/1/0001 12:00:00 AM
DateTime.MaxValue = 23:59:59.9999999, December 31, 9999, 
                    exactly one 100-nanosecond tick 
                    before 00:00:00, January 1, 10000

MSDN: DateTime.MinValue


Odnośnie serwera Sql

datetime
Data i godzina od 1 stycznia 1753 do 31 grudnia 9999, z dokładnością do jednej trzystu sekundy (odpowiednik 3,33 milisekundy lub 0,00333 sekundy). Wartości są zaokrąglane do przyrostów co .000, .003 lub .007 sekundy

smalldatetime
Data i czas od 1 stycznia 1900 r. do 6 czerwca 2079 r., z dokładnością do minuty. małe wartości czasu trwania z 29,998 sekund lub mniej są zaokrąglane w dół do najbliższej minuty; wartości z 29,999 sekund lub więcej są zaokrąglane w górę do najbliższej minuty.

MSDN: Sql Server DateTime i SmallDateTime


Na koniec, jeśli przekażesz C # DateTimejako ciąg do sql, musisz sformatować go w następujący sposób, aby zachować maksymalną precyzję i zapobiec wyrzucaniu przez serwer sql podobnego błędu.

string sqlTimeAsString = myDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff");

Aktualizacja (8 lat później)

Rozważ użycie DateTime2typu danych sql, który lepiej pasuje do .net DateTimez zakresem dat 0001-01-01 through 9999-12-31i zakresem czasu00:00:00 through 23:59:59.9999999

string dateTime2String = myDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffffff");

MSDN datetime2 (Transact-SQL)

Robert Paulson
źródło
6
Dzięki za wskaźnik dotyczący DateTimebraku wartości null w C #!
Tomas Aschan
80

Uważam, że użycie następujących elementów działa całkiem dobrze w przypadku dat minimalnych / maksymalnych SQL po wielu błędach związanych z bazą danych:

DateTime rngMin = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;

DateTime rngMax = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;
Chrismean
źródło
2
To powinno dostać najwięcej głosów i jest również poprawną odpowiedzią.
Taha Rehman Siddiqui
Należy jednak pamiętać, że między DateTime.MaxValuea i jest kilka różnic SqlDateTime.MaxValue.Value. SQL Server 2014 i SQL Server 2016 (nie sprawdzałem innych) akceptują, DateTime.MaxValuektóry - co zabawne - jest większy niż SqlDateTime.MaxValue.Value.
Manfred,
10

Uważaj podczas porównywania .Net DateTime z SqlDateTime.MinValue lub MaxValue. Na przykład poniższy przykład zgłosi wyjątek:

DateTime dte = new DateTime(1000, 1, 1);
if (dte >= SqlDateTime.MinValue)
    //do something

Powodem jest to, że MinValue zwraca SqlDateTime, a nie DateTime. Dlatego .Net próbuje przekonwertować dte na SqlDateTime w celu porównania, a ponieważ znajduje się poza dopuszczalnym zakresem SqlDateTime, zgłasza wyjątek.

Jednym z rozwiązań jest porównanie DateTime z SqlDateTime.MinValue. Wartość .

Phil Haselden
źródło
1
Istnieje również możliwość użycia SqlDateTime.MinValue.Valuelub SqlDateTime.MaxValue.Valueobu typów DateTime. Nie wiem, kiedy te zostały wprowadzone. Należy jednak pamiętać, że między DateTime.MaxValuea i jest kilka różnic SqlDateTime.MaxValue.Value. SQL Server 2014 i SQL Server 2016 (nie sprawdzałem innych) akceptują to DateTime.MaxValue- wystarczająco zabawne jest większe niż SqlDateTime.MaxValue.Value.
Manfred,
9

Kod, który masz dla dwóch kolumn, wygląda dobrze. Poszukaj innych kolumn z datą i godziną w tej klasie mapowania. Włącz również logowanie w kontekście danych, aby wyświetlić zapytanie i parametry.

dc.Log = Console.Out;

DateTime jest inicjowany na 0 C # - czyli 0001-01-01. Jest to przesyłane przez linqtosql do bazy danych za pośrednictwem literału ciągu sql: „0001-01-01”. Sql nie może przeanalizować daty i godziny T-Sql od tej daty.

Można sobie z tym poradzić na kilka sposobów:

  • Upewnij się, że wszystkie daty zostały zainicjowane wartością, którą SQL może obsłużyć (na przykład Sql's 0: 1900-01-01)
  • Upewnij się, że wszystkie czasy data może być niekiedy pomijane są dopuszczające wartość null datetimes
Amy B.
źródło
1
Zwykle używam 1970-01-01, który jest powszechną epoką dla czasu komputerowego (unix TIME_T i JavaScript)
Tracker1
Dzięki za wskazówkę dotyczącą przekierowania dziennika do Console.Out.
Jan Aagaard
8

Ten błąd występuje, jeśli próbujesz ustawić zmienną typu DateTime na null . Zadeklaruj zmienną jako dopuszczającą wartość null, tj. DateTime? . To rozwiąże problem.

Altaf Patel
źródło
1
To była odpowiedź na moje przepełnienie, miałem drugą datę na moim stole, której nie podawałem wartości, więc kiedy ustawiłem ją jako zerową, wstawka działała. Dzięki!
mkimmet
3

Czasami, aby napisać mniej kodu, używa się serwera SQL do ustawiania pól, takich jak data, godzina i identyfikator podczas wstawiania, ustawiając domyślną wartość pól na GETDATE()lub NEWID().

W takich przypadkach właściwość Wartość automatycznie generowana tych pól w klasach jednostek powinna mieć wartość true.

W ten sposób nie musisz ustawiać wartości w kodzie (zapobieganie zużyciu energii !!!) i nigdy nie widzisz tego wyjątku.

Haghpanah
źródło
2

Użyj metody rozszerzenia

 public static object ToSafeDbDateDBnull(this object objectstring)
    {
        try
        {
            if ((DateTime)objectstring >= SqlDateTime.MinValue)
            {
                return objectstring;
            }
            else
            {
                return DBNull.Value;
            }
        }
        catch (Exception)
        {

            return DBNull.Value;
        }

    }

DateTime objdte = new DateTime(1000, 1, 1);
dte.ToSafeDbDateDBnull();
MSTdev
źródło
1

Zwykle oznacza to, że do zapytania jest wysyłana wartość null zamiast żądanej wartości, możesz spróbować uruchomić program SQL Profiler, aby zobaczyć dokładnie, co jest przekazywane do SQL Server z linq.

Dozorca więzienny
źródło
1

Zwykle ten rodzaj błędu pojawia się, gdy wykonujesz konwersję lub analizowanie daty i godziny. Sprawdź ustawienia kalendarza na serwerze, na którym jest hostowana aplikacja, głównie strefę czasową i format krótkiej daty, i upewnij się, że jest ustawiona odpowiednia strefa czasowa dla lokalizacji. Mam nadzieję, że to rozwiąże problem.

Sushil Kumar Naik
źródło
0

Widzę to samo. Błąd nie występuje przy wstawianiu wiersza, ale przy aktualizacji. tabela, do której się odwołuję, ma dwie kolumny DateTime, z których żadna nie dopuszcza wartości null.

Skończyłem scenariusz do pobrania wiersza i natychmiastowego zapisania go (bez zmian danych). Get działa dobrze, ale aktualizacja się nie udaje.

Używamy NHibernate 3.3.1.4000

Tevya
źródło
0

Jeśli używasz NHibernate, sprawdź, czy odpowiednie właściwości DateTime, które mają wartość null, są ustawione na wartość null w mapowaniach.

wysypka
źródło
0

Jeśli umieścisz wartość null Datetime, taką jak DateTime? w twoim modelu nie zgłasza wyjątku. rozwiązałem ten problem w moim przypadku

baptiste baume
źródło
0

W moim przypadku ten błąd został zgłoszony, ponieważ kolumna daty tabeli nie może mieć wartości null

Jak poniżej:

Create Table #TempTable(
 ...
 ApprovalDate datatime not null.
 ...)

Aby uniknąć tego błędu, po prostu ustaw jego wartość zerową

 Create Table #TempTable(
 ...
 ApprovalDate datatime null.
 ...)
Ravi Makwana
źródło
-3

DateTime.MinValue i DateTime.MaxValue

DateTime.MinValue = 1/1/0001 12:00:00 AM

DateTime.MaxValue = 23:59:59.9999999, December 31, 9999, 

                exactly one 100-nanosecond tick 

                before 00:00:00, January 1, 10000 
Cindrella
źródło