Fehler - SqlDateTime-Überlauf. Muss zwischen dem 1.1.1753, 12:00:00 Uhr und dem 31.12.19999, 23:59:59 Uhr liegen

80

Ich habe diesen Code verwendet, den ich geschrieben habe, und er funktioniert auf diese unklarste Weise. Ich möchte eine Zeile in die Datenbank einfügen, die zwei Spalten von DateTime enthält:

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

Und doch erhalte ich beim Aktualisieren der Datenbank folgende Fehlermeldung:

SqlDateTime-Überlauf. Muss zwischen dem 1.1.1753, 12:00:00 Uhr und dem 31.12.19999, 23:59:59 Uhr liegen.

Ich habe sogar versucht, einen eingefügten Wert aus der Datenbank zu kopieren und ihn fest in das zu aktualisierende Objekt zu codieren:

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

Immer noch der gleiche Fehler, der seltsame Teil ist, dass der obige Trick für die erste Einfügung in die Datenbank funktioniert hat, aber von da an fehlgeschlagen ist. Irgendwelche Ideen, was los ist?

Drew Noakes
quelle
Veröffentlichen Sie Ihren Code. Sie können auch prüfen, was linq unter der Decke baut.
NotMe

Antworten:

86

A DateTimein C # ist ein Werttyp, kein Referenztyp und kann daher nicht null sein. DateTime.MinValueDies kann jedoch die Konstante sein, die außerhalb des Bereichs des Datentyps SQL Server liegt DATETIME.

Werttypen haben garantiert immer einen (Standard-) Wert (von Null), ohne dass dies immer explizit festgelegt werden muss (in diesem Fall DateTime.MinValue).

Schlussfolgerung ist, dass Sie wahrscheinlich einen nicht festgelegten DateTime-Wert haben, den Sie an die Datenbank übergeben möchten.

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


In Bezug auf SQL Server

datetime Datums-
und Uhrzeitdaten vom 1. Januar 1753 bis zum 31. Dezember 9999 mit einer Genauigkeit von einer Dreihundertstelsekunde (entspricht 3,33 Millisekunden oder 0,00333 Sekunden). Die Werte werden in Schritten von .000, .003 oder .007 Sekunden gerundet

smalldatetime Datums-
und Zeitdaten vom 1. Januar 1900 bis 6. Juni 2079 mit minutengenauer Genauigkeit. Werte für kleine Daten mit 29,998 Sekunden oder weniger werden auf die nächste Minute abgerundet. Werte mit 29,999 Sekunden oder höher werden auf die nächste Minute aufgerundet.

MSDN: SQL Server DateTime und SmallDateTime


Wenn Sie ein C # DateTimeals Zeichenfolge an SQL übergeben, müssen Sie es wie folgt formatieren, um die maximale Genauigkeit beizubehalten und zu verhindern, dass der SQL Server einen ähnlichen Fehler auslöst.

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

Update (8 Jahre später)

Erwägen Sie die Verwendung des SQL- DateTime2Datentyps, der DateTimemit Datums- 0001-01-01 through 9999-12-31und Zeitbereich besser mit dem .net übereinstimmt00:00:00 through 23:59:59.9999999

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

MSDN datetime2 (Transact-SQL)

Robert Paulson
quelle
6
Vielen Dank für den DateTimeHinweis, dass C # nicht nullbar ist!
Tomas Aschan
79

Ich finde, dass die Verwendung der folgenden Funktionen für SQL-Min / Max-Daten nach vielen DB-bezogenen Fehlern recht gut funktioniert:

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

DateTime rngMax = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;
Chrismean
quelle
2
Dies hätte die meisten Stimmen bekommen sollen und ist auch die richtige Antwort.
Taha Rehman Siddiqui
Beachten Sie jedoch, dass zwischen DateTime.MaxValueund ein paar Zeckenunterschiede bestehen SqlDateTime.MaxValue.Value. SQL Server 2014 und SQL Server 2016 (andere nicht überprüft) akzeptieren, DateTime.MaxValuewas - lustig genug - größer ist als SqlDateTime.MaxValue.Value.
Manfred
10

Seien Sie vorsichtig, wenn Sie eine .Net DateTime mit SqlDateTime.MinValue oder MaxValue vergleichen. Folgendes löst beispielsweise eine Ausnahme aus:

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

Der Grund ist, dass MinValue eine SqlDateTime und keine DateTime zurückgibt. Daher versucht .Net, dte zum Vergleich in eine SqlDateTime zu konvertieren, und löst die Ausnahme aus, da es außerhalb des zulässigen SqlDateTime-Bereichs liegt.

Eine Lösung hierfür besteht darin, Ihre DateTime mit SqlDateTime.MinValue zu vergleichen. Wert .

Phil Haselden
quelle
1
Es besteht auch die Möglichkeit , zu verwenden , SqlDateTime.MinValue.Valueoder SqlDateTime.MaxValue.Valuevon denen beide vom Typ sind DateTime. Ich weiß nicht, wann diese eingeführt wurden. Beachten Sie jedoch, dass zwischen DateTime.MaxValueund ein paar Zeckenunterschiede bestehen SqlDateTime.MaxValue.Value. SQL Server 2014 und SQL Server 2016 (andere nicht überprüft) akzeptieren DateTime.MaxValuewelche - lustig genug ist größer als SqlDateTime.MaxValue.Value.
Manfred
9

Der Code, den Sie für die beiden Spalten haben, sieht in Ordnung aus. Suchen Sie nach anderen Datums- / Uhrzeitspalten in dieser Zuordnungsklasse. Aktivieren Sie außerdem die Protokollierung im Datenkontext, um die Abfrage und die Parameter anzuzeigen.

dc.Log = Console.Out;

DateTime wird auf c # 's 0 initialisiert - das ist 0001-01-01. Dies wird von linqtosql über das SQL-String-Literal '0001-01-01' an die Datenbank übertragen. SQL kann ab diesem Datum keine T-SQL-Datums- und Uhrzeitangabe analysieren.

Es gibt verschiedene Möglichkeiten, damit umzugehen:

  • Stellen Sie sicher, dass Sie alle Datums- und Uhrzeitangaben mit einem Wert initialisieren, den SQL verarbeiten kann (z. B. SQL 0: 1900-01-01).
  • Stellen Sie sicher , dass alle Datum Zeiten , die gelegentlich weggelassen werden können , sind auf NULL festlegbare Datetimes
Amy B.
quelle
1
Normalerweise verwende ich 1970-01-01, eine häufige Epoche für die Computerzeit (Unix TIME_T und JavaScript)
Tracker1
Vielen Dank für den Tipp, das Protokoll an Console.Out umzuleiten.
Jan Aagaard
8

Dieser Fehler tritt auf, wenn Sie versuchen, eine Variable vom Typ DateTime auf null zu setzen . Deklarieren Sie die Variable als nullbar, dh DateTime? . Dies wird das Problem lösen.

Altaf Patel
quelle
1
Dies war die Antwort auf meinen Überlauf. Ich hatte ein zweites Datum auf meinem Tisch, dem ich keinen Wert gab. Sobald ich es als nullwert festgelegt hatte, funktionierte die Einfügung. Vielen Dank!
mkimmet
3

Um weniger Code zu schreiben, wird manchmal SQL Server verwendet, um Felder wie Datum, Uhrzeit und ID beim Einfügen festzulegen, indem der Standardwert für Felder auf GETDATE()oder gesetzt wird NEWID().

In solchen Fällen sollte die Eigenschaft " Automatisch generierter Wert" dieser Felder in Entitätsklassen auf "true" gesetzt werden.

Auf diese Weise müssen Sie keine Werte im Code festlegen (um den Energieverbrauch zu vermeiden !!!) und sehen diese Ausnahme nie.

Haghpanah
quelle
2

Verwenden Sie die Erweiterungsmethode

 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
quelle
1

Dies bedeutet normalerweise, dass anstelle des gewünschten Werts eine Null an die Abfrage gesendet wird. Sie können versuchen, den SQL Profiler auszuführen, um genau zu sehen, was von linq an SQL Server übergeben wird.

Schlüsselfertig
quelle
1

Normalerweise tritt diese Art von Fehler auf, wenn Sie DateTime konvertieren oder analysieren. Überprüfen Sie die Kalendereinstellung auf dem Server, auf dem die Anwendung gehostet wird, hauptsächlich die Zeitzone und das kurze Datumsformat, und stellen Sie sicher, dass die richtige Zeitzone für den Standort eingestellt ist. Hoffe, dies würde das Problem lösen.

Sushil Kumar Naik
quelle
0

Ich sehe das Gleiche. Der Fehler tritt nicht beim Einfügen einer Zeile, sondern bei einem Update auf. Die Tabelle, auf die ich verweise, enthält zwei DateTime-Spalten, von denen keine nullwertfähig ist.

Ich habe das Szenario darauf reduziert, die Zeile abzurufen und sofort zu speichern (keine Datenänderungen). Das Get funktioniert einwandfrei, aber das Update schlägt fehl.

Wir verwenden NHibernate 3.3.1.4000

Tevya
quelle
0

Wenn Sie NHibernate verwenden, überprüfen Sie, ob die entsprechenden DateTime-Eigenschaften, die nullbar sind, in den Zuordnungen auf nullable gesetzt sind.

Arash
quelle
0

Wenn Sie Datetime wie DateTime auf null setzen? In Ihrem Modell wird keine Ausnahme ausgelöst. Ich habe das Problem in meinem Fall so gelöst

baptiste baume
quelle
0

In meinem Fall Dieser Fehler wurde ausgelöst, da die Tabellendatumspalte nicht nullfähig ist

Wie nachstehend:

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

Um diesen Fehler zu vermeiden, machen Sie ihn einfach nullfähig

 Create Table #TempTable(
 ...
 ApprovalDate datatime null.
 ...)
Ravi Makwana
quelle
-3

DateTime.MinValue und 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
quelle