Warum verwendet der EF5-Code zuerst datetime2, wenn er eine nullbare Datetime in die Datenbank einfügt?

7

Ich speichere ein Cart-Objekt in der Datenbank mit einer nullbaren Datetime. Dies ist der Fehler, den ich bekomme:

  

Die Konvertierung eines Datetime2-Datentyps in einen Datetime-Datentyp   ergab einen Wert außerhalb des Bereichs.

Es gibt ziemlich viele Stackoverflow-Beiträge, die Korrekturen für dieses Problem dokumentieren. Wenn Code jedoch zuerst die Datenbank erstellt, erstellt er das Feld als DateTime (Nullen zulassen). Aus irgendeinem Grund versucht Code jedoch zuerst, ein DateTime2-Feld einzufügen.

Ich wundere mich, warum EF das Feld in einer Richtung erstellt, aber mit einem anderen Typ für dasselbe Feld einfügt.

Dies ist das Domänenobjekt:

%Vor%

Das Modell:

%Vor%

Also sind sowohl OpeningDateUtc als auch ClosingDateUtc vom Typ DateTime?.

So wird die Datenbank zuerst mit dem EF-Code generiert:

Die OpeningDateUtc und ClosingDateUtc werden als Nullable DateTime Feld erstellt.

Warum also, wenn ich mit IDBContext.SaveChanges() speichere, lautet das für die Abfrage generierte SQL:

%Vor%

Der interessante Teil ist @4 datetime2(7),@5 datetime2(7) .

Ich verstehe, dass ich dieses Problem beheben konnte, indem ich ein .HasColumnType("datetime2") zur Warenkorbkarte hinzufügte, aber es beantwortet nicht, warum EF5 (und wahrscheinlich ältere Versionen) sie auf nullable datetime setzen.

    
Matt R 09.01.2013, 21:03
quelle

2 Antworten

15

Der DateTime -Typ in .NET hat den gleichen Bereich und die gleiche Genauigkeit wie datetime2 in SQL Server. Wenn EF eine Spalte datetime oder datetime2 in SQL Server einfügt oder aktualisiert, wird die Modelleigenschaft in den Typ konvertiert, der den gesamten Bereich von DateTime in .NET enthalten kann, also datetime2 . Die Konvertierung in datetime würde fehlschlagen, wenn die DateTime -Eigenschaft nicht im Bereich von datetime in SQL Server liegt.

Das Problem, das die Ausnahme verursacht, sind übrigens nicht die zwei Nullable OpeningDateUtc und ClosingDateUtc Spalten, sondern der CreatedOnUtc Wert, der '0001-01-01 00:00:00' in Ihrem SQL Snippet ist, dh CreatedOnUtc ist anscheinend nicht initialisiert in Ihrer Modelleinheit. Das früheste Datum, das datetime in SQL Server speichern kann, ist im Jahr 1750, also passt Jahr 0001 nicht in den Typ (aber es würde in datetime2 passen).

Die Lösung besteht also darin, CreatedOnUtc auf einen gültigen datetime Wert zu setzen oder - wie Sie wissen - die Typen als datetime2 in Ihrem Mapping zu definieren.

Aber ich stimme zu, es würde weniger Verwirrung geben, wenn EF DateTime Eigenschaften standardmäßig auf datetime2 abbildet.

    
Slauma 09.01.2013, 21:17
quelle
11

Das EF Team hat diesen speziellen Punkt während eines der Design-Meetings besprochen. Die Entscheidung war, das aktuelle Verhalten so zu lassen, wie es ist. Hier sind die Meeting-Notizen , die Ihnen mehr bieten können Kontext.

    
Pawel 09.01.2013 23:05
quelle