2009-03-14 18 views
5

Sto lavorando a un progetto ASP.NET MVC con NHibernate come back-end e sto avendo qualche problema a recuperare alcune date per scrivere nuovamente alle tabelle del mio database SQL Server.NHibernate non persisterà DateTime SqlDateTime overflow

Questi campi di date NON sono annullabili, quindi le numerose risposte qui su come impostare i tempi di registrazione annulli non hanno aiutato.

Fondamentalmente quando provo a salvare l'entità che ha un campo DateAdded e LastUpdated, ricevo un'eccezione di overflow SqlDateTime. Ho avuto un problema simile in passato in cui stavo cercando di scrivere un campo datetime in una colonna smalldatetime, aggiornando il tipo sulla colonna apparso per risolvere il problema. Il mio istinto è che sarà un problema con la definizione della tabella o qualche tipo di tipi di dati incompatibili, e l'eccezione di overflow è un po 'un vagabondo.

Ho allegato un esempio della definizione della tabella e la query che NHibernate sta tentando di eseguire, qualsiasi aiuto o suggerimento sarebbe molto apprezzato.

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' 

In risposta alle le risposte/commenti, io sto usando Fluent NHibernate e la mappatura generato è inferiore

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

La tabella e SQL sembrano ok. Quella query SQL funziona se provi a eseguirlo manualmente? Potrebbe valere la pena di postare il codice e il file di mappatura di ibernazione qui –

+0

Sì, la query viene eseguita correttamente in SQL Query Analyzer, tranne che devo cambiare le virgolette singole doppie attorno al datetimes (come stringhe di stile utc) alle virgolette singole, questa query è generato da nibernato –

risposta

0

Perché @ p3 p4 e @ hanno apici 2x? Copia e incolla errore?

non posso controllare (non c'è bisogno di SQL installato qui), ma dovrebbe il millisecond separator non essere "punto", cioè "2009-03-14 14: 29: 37.000"

@ p3 viene "prima", @ p4 è "dopo" qui:

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

Sì, ho pensato che il modo in cui rendeva le date era un po 'strano anche, tuttavia funziona in query analyzer, tranne che devo scambiare le virgolette per le virgolette singole. Ho esaminato il capitolo 5 del docus vietato pensando che potrei dire come correggere il dialetto, ma sembra possibile –

+0

Il formato 2009-03-14 14: 29: 37: 000 è però sbagliato per SQL Server – gbn

+0

Il dialetto potrebbe sii il tuo problema Perché dici che non sembra possibile impostarlo? Come stai creando la tua SessionFactory? Stai leggendo da un file di configurazione o creandolo a livello di programmazione? –

0

Lo script SQL nella tua domanda eseguito bene sul mio installazione di SQL 2005 (una volta ho risolto i problemi di citazione raccolti da GBN). E anche la tua mappatura va bene. Mi dispiace di essere di così poco aiuto.

0

Stavo usando s # architecture/fluentnhibernate per creare questa mappatura, ho aggiornato alla versione più recente e sembra funzionare bene.

17

In realtà il motivo dietro la scena è:

Quando NHibernate legge la riga dalla db, il valore è nullo, e questo è ciò che la sessione si ricorda. Quando l'oggetto viene reidratato da NHibernate, la data viene impostata sul valore DateTime.MinValue. Quando la Sessione è sincronizzata con il db, NHibernate presume che qualcosa è cambiato, perché lo stato corrente e lo stato precedente sono diversi e prova ad aggiornare la riga. Che a sua volta non riesce, perché DateTime.MinValue non si adatta a una colonna datetime di SqlServer.

La soluzione: rendere il vostro datetime nullable inserendo? alla fine di Datetime come DateTime? o Nullable

articolo complet sono disponibili all'indirizzo: nhibernate-sqldatetime-overflow-issue

+0

Risolto il mio problema. –

0

Solo una cronaca, ho lavorato sulla migrazione di un'applicazione esistente per NHibernate da una varietà di incorporato accesso ai dati si avvicina. Questo problema si è verificato rapidamente e ho trovato una soluzione semplice che ha ridotto al minimo l'impatto sul codice dell'applicazione funzionale esistente. Poiché in alcuni casi migriamo per livello, l'interfaccia della classe dati doveva rimanere stabile se possibile.La soluzione era quella di continuare a utilizzare i tipi DateTime per l'interfaccia pubblica, aggiungere metodi di estensione ai tipi di campi privati ​​per convertire da MinValue a null e tornare sui campi privati ​​negli accessor e mappare nHibernate ai campi privati.

JF

1

Ho affrontato lo stesso problema con il tavolo colonne datetime non annullabili e un overflow SqlDateTime su un salvataggio.

Nel mio caso il problema effettivo era che il salvataggio ha attivato un session.flush che causa un aggiornamento ad alcuni oggetti caricati in precedenza utilizzando la stessa sessione. Questo oggetto aveva i "campi datetime in cui il campo datetime nullable avrebbe dovuto essere utilizzato".

In altre parole: provare a eseguire una sessione.flush prima del salvataggio o dell'aggiornamento per verificare se il problema è causato dall'utilizzo precedente dello stesso oggetto sessione.

La speranza che aiuta chiunque.