2009-03-14 12 views
5

Ich arbeite an einem ASP.NET MVC-Projekt mit NHibernate als Backend und habe einige Probleme ein paar Tage, zurück zu meinen SQL Server-Datenbanktabellen zu schreiben.NHibernate wird nicht Datetime besteht SqlDateTime Überlauf

Diese Datumsfelder sind NICHT NULL-Werte zulässig, daher haben die vielen Antworten hier nicht geholfen.

Wenn ich versuche, die Entität zu speichern, die ein DateAdded und ein LastUpdated Felder enthält, erhalte ich eine SqlDateTime Overflow-Ausnahme. Ich hatte ein ähnliches Problem in der Vergangenheit, wo ich versuchte, ein Datetime-Feld in eine Smalldatetime-Spalte zu schreiben, die Aktualisierung des Typs auf der Spalte erschien, um das Problem zu beheben. Mein Bauchgefühl ist, dass es ein Problem mit der Tabellendefinition oder irgendeine Art von inkompatiblen Datentypen sein wird, und die Überlaufausnahme ist ein bisschen ein Burn Oke.

Ich habe ein Beispiel der Tabellendefinition angefügt und die Abfrage, die NHibernate versucht auszuführen, jede Hilfe oder Vorschläge würden sehr geschätzt.

CREATE TABLE [dbo].[CustomPages](
    [ID] [uniqueidentifier] NOT NULL, 
    [StoreID] [uniqueidentifier] NOT NULL, 
    [DateAdded] [datetime] NOT NULL, 
    [AddedByID] [uniqueidentifier] NOT NULL, 
    [LastUpdated] [datetime] NOT NULL, 
    [LastUpdatedByID] [uniqueidentifier] NOT NULL, 
    [Title] [nvarchar](150) NOT NULL, 
    [Term] [nvarchar](150) NOT NULL, 
    [Content] [ntext] NULL 
) 

exec sp_executesql N'INSERT INTO CustomPages (Title, Term, Content, LastUpdated, DateAdded, StoreID, LastUpdatedById, AddedById, ID) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)',N'@p0 
nvarchar(21),@p1 nvarchar(21),@p2 nvarchar(33),@p3 datetime,@p4 datetime,@p5 uniqueidentifier,@p6 uniqueidentifier,@p7 uniqueidentifier,@p8 uniqueidentifier',@p0=N'Size and Colour 
Chart',@p1=N'size-and-colour-chart',@p2=N'This is the size and colour chart',@p3=''2009-03-14 14:29:37:000'',@p4=''2009-03-14 
14:29:37:000'',@p5='48315F9F-0E00-4654-A2C0-62FB466E529D',@p6='1480221A-605A-4D72-B0E5-E1FE72C5D43C',@p7='1480221A-605A-4D72-B0E5-E1FE72C5D43C',@p8='1E421F9E-9A00-49CF-9180-DCD22FCE7F55' 

Als Reaktion die Antworten/Kommentare, bin ich mit Fluent NHibernate und die erzeugte Abbildung ist unter

public CustomPageMap() { 

      WithTable("CustomPages"); 

      Id(x => x.ID, "ID") 
       .WithUnsavedValue(Guid.Empty) 
      . GeneratedBy.Guid(); 

      References(x => x.Store, "StoreID"); 

      Map(x => x.DateAdded, "DateAdded"); 
      References(x => x.AddedBy, "AddedById"); 
      Map(x => x.LastUpdated, "LastUpdated"); 
      References(x => x.LastUpdatedBy, "LastUpdatedById"); 


      Map(x => x.Title, "Title"); 
      Map(x => x.Term, "Term"); 
      Map(x => x.Content, "Content"); 

     } 

    <?xml version="1.0" encoding="utf-8"?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false" assembly="MyNamespace.Core" namespace="MyNamespace.Core"> 
<class name="CustomPage" table="CustomPages" xmlns="urn:nhibernate-mapping-2.2"> 
<id name="ID" column="ID" type="Guid" unsaved-value="00000000-0000-0000-0000-000000000000"><generator class="guid" /></id> 
<property name="Title" column="Title" length="100" type="String"><column name="Title" /></property> 
<property name="Term" column="Term" length="100" type="String"><column name="Term" /></property> 
<property name="Content" column="Content" length="100" type="String"><column name="Content" /></property> 
<property name="LastUpdated" column="LastUpdated" type="DateTime"><column name="LastUpdated" /></property> 
<property name="DateAdded" column="DateAdded" type="DateTime"><column name="DateAdded" /></property> 
<many-to-one name="Store" column="StoreID" /><many-to-one name="LastUpdatedBy" column="LastUpdatedById" /> 
<many-to-one name="AddedBy" column="AddedById" /></class></hibernate-mapping> 
+0

Ihre Tabelle und die SQL scheinen in Ordnung. Funktioniert diese SQL-Abfrage, wenn Sie versuchen, es manuell auszuführen? Es lohnt sich möglicherweise, den Code und die Hibernate-Mapping-Datei hier zu posten –

+0

Ja, die Abfrage wird in SQL Query Analyzer ordnungsgemäß ausgeführt, außer dass ich die doppelten einfachen Anführungszeichen um die Datumsangaben (als utc-Stilzeichenfolgen) in einfache Anführungszeichen ändern muss generiert von nhibernate –

Antwort

0

Warum p4 do @ p3 und @ 2x Apostrophe haben? Fehler kopieren und einfügen?

Ich kann nicht überprüfen (nicht SQL hier installiert hat), soll aber die millisecond separator nicht "Punkt" sein, das heißt, "2009-03-14 14: 29: 37.000"

@ p3 wird „vor“, @ p4 „nach“ hier: ganz gut ausgeführt auf meiner SQL 2005-Installation in Ihrer Frage

exec sp_executesql 
    N'INSERT INTO CustomPages (Title, Term, Content, LastUpdated, DateAdded, StoreID, LastUpdatedById, AddedById, ID) 
    VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)', 
    N'@p0 nvarchar(21),@p1 nvarchar(21),@p2 nvarchar(33),@p3 datetime,@p4 datetime,@p5 uniqueidentifier,@p6 uniqueidentifier,@p7 uniqueidentifier,@p8 uniqueidentifier', 

    @p0=N'Size and Colour Chart', 
    @p1=N'size-and-colour-chart', 
    @p2=N'This is the size and colour chart', 
    @p3=''2009-03-14 14:29:37:000'', --quotes + dot wrong? 
    @p4='2009-03-14 14:29:37.000', --quotes + dot correct? 
    @p5='48315F9F-0E00-4654-A2C0-62FB466E529D', 
    @p6='1480221A-605A-4D72-B0E5-E1FE72C5D43C', 
    @p7='1480221A-605A-4D72-B0E5-E1FE72C5D43C', 
    @p8='1E421F9E-9A00-49CF-9180-DCD22FCE7F55' 
+0

Ja, ich dachte, die Art, wie es die Daten gerendert wurde, war ein bisschen seltsam, aber es funktioniert in Query Analyzer, außer ich muss die doppelten Anführungszeichen für einfache Anführungszeichen tauschen. Ich schaute in Kapitel 5 der Nhibernate Doco denken, ich könnte Nhibernate sagen, wie man den Dialekt korrigieren, aber es sieht möglich –

+0

Das 2009-03-14 14: 29: 37: 000-Format ist falsch, obwohl für SQL Server – gbn

+0

Der Dialekt könnte sei dein Problem. Warum sagst du, dass es nicht möglich ist, das festzulegen? Wie erstellst du deine SessionFactory? Liest du es aus einer Konfigurationsdatei oder programmierst du es? –

0

Der SQL-Skript (einmal fixierte ich die Kursfragen nahmen von gbn nach oben). Und Ihr Mapping sieht auch gut aus. Tut mir leid, so wenig Hilfe zu haben.

0

Ich war mit s # Architektur/FluentNHibernate diese Zuordnung zu erstellen, habe ich auf die neueste Version aktualisiert und es scheint, adaequat zu sein.

17

Eigentlich ist der Grund hinter der Szene:

Wenn NHibernate liest die Zeile aus der db, der Wert ist null, und das ist, was die Sitzung erinnert. Wenn das Objekt von NHibernate rehydriert wird, wird das Date auf den Wert DateTime.MinValue gesetzt. Wenn die Sitzung mit der Datenbank synchronisiert wird, nimmt NHibernate an, dass sich etwas geändert hat, da sich currentState und previousState unterscheiden und versucht, die Zeile zu aktualisieren. Dies wiederum schlägt fehl, da DateTime.MinValue nicht in eine SqlServer-Datetime-Spalte passt.

Die Lösung: machen Sie Ihre Datetime Nullable entweder durch setzen? am Ende von Datetime wie DateTime? oder Nullable

complet Artikel finden Sie unter: nhibernate-sqldatetime-overflow-issue

+0

Mein Problem wurde gelöst. –

0

Nur ein FYI, auf die Migration einer bestehenden Anwendung auf NHibernate aus einer Vielzahl von Embedded Data Access nähert sich arbeiten Ich habe. Dieses Problem trat schnell auf und ich fand eine einfache Lösung, die die Auswirkungen auf den vorhandenen funktionalen Anwendungscode minimiert. Weil wir durch die Schicht in einigen Fällen migrieren, um die Datenklasse Schnittstelle benötigt stabil bleiben, wenn überhaupt möglich.Die Lösung bestand darin, weiterhin DateTime-Typen für die öffentliche Schnittstelle zu verwenden, den privaten Feldtypen Erweiterungsmethoden hinzuzufügen, um MinValue in null und zurück in die privaten Felder in den Accessoren zu konvertieren, und nHibernate den privaten Feldern zuzuordnen.

JF

1

stand ich vor dem gleichen Problem Tabelle mit nicht NULL festlegbare Datetime-Spalten und eine SqlDateTime Überlauf auf den Schuß ab.

In meinem Fall war das eigentliche Problem, dass die Speicherung eine session.flush ausgelöst hat, die eine Aktualisierung auf ein Objekt verursacht, das früher mit derselben Sitzung geladen wurde. Für dieses Objekt wurden die Felder "datetime fields, in denen Nullable datetime field verwendet werden sollte" ausgegeben.

Mit anderen Worten: Versuchen Sie, vor dem Speichern oder Aktualisieren eine session.flush auszuführen, um zu prüfen, ob das Problem möglicherweise durch die frühere Verwendung desselben Sitzungsobjekts verursacht wurde.

Hoffnung, die jedem hilft.

Verwandte Themen