2009-01-22 6 views
58

Używam tego kodu, który napisałem i działa w ten najbardziej niejasny sposób. Chciałabym wstawić wiersz do bazy danych, która zawiera dwie kolumny DateTime:- Przepełnienie SqlDateTime. Musi być między 1/1/1753 12:00:00 i 12/31/9999 11:59:59 PM

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

A jednak, kiedy aktualizuje bazę danych otrzymuję ten błąd:

SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.

Mam nawet próbował kopiowania dodaje wartość z bazy danych i ciężko kodem go w obiekt jest aktualizowany:

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

nadal ten sam błąd, dziwne jest to, że powyższa sztuczka pracował dla pierwszego Włożyć do DB, ale f z tamtej ziemi. Jakieś pomysły, co się dzieje?

+0

postu kod. Możesz również rozważyć sprawdzenie, co linq buduje pod kołdrą. – NotMe

Odpowiedz

1

Zazwyczaj oznacza to, że do kwerendy wysłano wartość zerową zamiast żądanej wartości, możesz spróbować uruchomić program SQL Profiler, aby zobaczyć dokładnie, co jest przekazywane do SQL Server z linq.

9

Kod dla dwóch kolumn wygląda dobrze. Poszukaj innych kolumn datetime na tej klasie odwzorowania. Ponadto włącz rejestrowanie danych w celu wyświetlenia zapytania i parametrów. To jest 0001-01-01. Jest to przekazywane przez linqtosql do bazy danych za pomocą dosłownej litery: "0001-01-01". Sql nie może parsować datetime T-Sql od tej daty.

Jest kilka sposobów radzenia sobie z tym:

  • Upewnij się zainicjować cały czas na bieżąco z wartości, która może obsługiwać SQL (takie jak SQL na 0: 1900-01-01)
  • Upewnij wszystkie przypadki daty, które mogą być od czasu do czasu są pominięte dopuszczające wartość null datetimes
+1

Zwykle używam 1970-01-01, co jest częstą epoką dla czasu komputera (unix TIME_T i JavaScript) – Tracker1

+0

Dzięki za podpowiedź przekierowania Log to Console.Out. –

68

DateTime C# jest typ wartości, a nie typu urządzenia, a więc nie może być zerowy. Może to być jednak stała wartość DateTime.MinValue, która znajduje się poza zakresem danych Sql Servers DATETIME.

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

Podsumowując, prawdopodobnie masz niepoprawioną 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


chodzi SQL Server

datetime
Date and time data from January 1, 1753 through December 31, 9999, to an accuracy of one three-hundredth of a second (equivalent to 3.33 milliseconds or 0.00333 seconds). Values are rounded to increments of .000, .003, or .007 seconds

smalldatetime
Date and time data from January 1, 1900, through June 6, 2079, with accuracy to the minute. smalldatetime values with 29.998 seconds or lower are rounded down to the nearest minute; values with 29.999 seconds or higher are rounded up to the nearest minute.

MSDN: Sql Server DateTime and SmallDateTime


Wreszcie, jeśli znajdziesz się przechodzącą C# DateTime jako ciąg do sql, należy sformatować go w następujący sposób, aby zachować maksymalną precyzję i zapobiec serwerowi sql z powodu podobnego błędu.

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

Update (8 lat później)

Rozważmy pomocą sql DateTime2 typ danych, który wyrównuje lepiej z .net DateTime z zakresu dat 0001-01-01 through 9999-12-31 i przedziale czasowym 00:00:00 through 23:59:59.9999999

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

MSDN datetime2 (Transact-SQL)

+5

Dzięki za wskaźnik o 'DateTime' nie jest zerowy w C#! –

3

Czasami aby pisać mniej kodu służy do serwera SQL posiada zestaw pól takich jak data, godzina i ID na wkładce poprzez ustawienie wartości domyślnej dla pola do GETDATE() lub NEWID().

W takich przypadkach Auto Generated wartość własność tych pól w klasach jednostka powinna być ustawiona na wartość true.

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

55

znajdę stosując następujące działa całkiem dobrze dla SQL min/max terminach po wielu DB związanych błędów:

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

DateTime rngMax = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue; 
+1

+1 działa dobrze dla mnie i tylko to, czego szukałem. –

+2

To powinno zdobyć najwięcej głosów i jest również poprawną odpowiedzią. –

+0

Tak! To działa! –

-1

Jeśli ur użyciu NHibernate ORM sprawdzić ur pliki DateTime być Nullable i ur NHibernate Mapa Pliki istnieją ustawiony na zerowy.

miałem ten problem i tryed wiele czasu, aby sprawdzić wszystkie kody i wreszcie go znaleźć.

+0

Proszę dokonać korekty swoich odpowiedzi, zanim je podasz. – normanthesquid

6

Uwaga na porównanie metody .Net DateTime z SqlDateTime.MinValue lub MaxValue. Na przykład, co następuje rzuci 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. Więc .Net próbuje przekonwertować dte do SqlDateTime dla porównania i ponieważ jest poza dopuszczalnym zakresem SqlDateTime, zgłasza wyjątek.

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

+1

+1 za ostrzeżenie o wyjątku czającym się w porównaniu. –

+0

Istnieje również opcja użycia 'SqlDateTime.MinValue.Value' lub' SqlDateTime.MaxValue.Value', z których oba są typu 'DateTime'. Nie wiem, kiedy zostały wprowadzone. Należy jednak pamiętać, że istnieje kilka różnic między "DateTime.MaxValue" i "SqlDateTime.MaxValue.Value". SQL Server 2014 i SQL Server 2016 (nie sprawdzały innych) akceptują 'DateTime.MaxValue', który - wystarczająco zabawny jest większy niż' SqlDateTime.MaxValue.Value'. – Manfred

0

widzę to samo. Błąd nie występuje po wstawieniu wiersza, ale w aktualizacji. tabela, do której się odwołuję, ma dwie kolumny DateTime, z których żadna nie jest null.

Dostałem scenariusz w dół, aby uzyskać wiersz i natychmiast go zapisać (brak zmian danych). Uzyskiwanie działa dobrze, ale aktualizacja kończy się niepowodzeniem.

Używamy NHibernate 3.3.1.4000

0

Zazwyczaj tego rodzaju błędem jest, gdy robisz konwersję DateTime lub analizowania. Sprawdź ustawienia kalendarza na serwerze, na którym hostowana jest aplikacja, głównie strefę czasową i krótki format daty, i upewnij się, że jest ustawiona we właściwej strefie czasowej dla lokalizacji. Mam nadzieję, że to rozwiąże problem.

-3

DateTime.MinValue i parametr 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 
3

Ten błąd występuje, jeśli próbuje ustawić zmienną typu DateTime do zerowej. Zadeklaruj zmienną jako zerową, tj. DateTime?. To rozwiąże problem.

+0

To była odpowiedź na moje przepełnienie, miałem drugą randkę na moim stole, której nie dawałem wartości, więc gdy ustawiłem ją jako zerową, działka działała. Dzięki! – mkimmet

0

Korzystanie rozszerzenie metoda

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();