2011-01-05 9 views
146

Ho il seguente codice nel mio HomeController:La conversione di un tipo di dati datetime2 a un tipo di dati datetime ha provocato un valore out-of-range

public ActionResult Edit(int id) 
    { 
     var ArticleToEdit = (from m in _db.ArticleSet where m.storyId == id select m).First(); 
     return View(ArticleToEdit); 
    } 

    [ValidateInput(false)] 
    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Edit(Article ArticleToEdit) 
    { 

     var originalArticle = (from m in _db.ArticleSet where m.storyId == ArticleToEdit.storyId select m).First(); 
     if (!ModelState.IsValid) 
      return View(originalArticle); 

     _db.ApplyPropertyChanges(originalArticle.EntityKey.EntitySetName, ArticleToEdit); 
     _db.SaveChanges(); 
     return RedirectToAction("Index"); 

    } 

E questa è la vista per il metodo Edit:

<% using (Html.BeginForm()) {%> 

    <fieldset> 
     <legend>Fields</legend> 
     <p> 
      <label for="headline">Headline</label> 
      <%= Html.TextBox("headline") %> 
     </p> 
     <p> 
      <label for="story">Story <span>(HTML Allowed)</span></label> 
      <%= Html.TextArea("story") %> 
     </p> 
     <p> 
      <label for="image">Image URL</label> 
      <%= Html.TextBox("image") %> 
     </p> 
     <p> 
      <input type="submit" value="Post" /> 
     </p> 
    </fieldset> 

<% } %> 

Quando mi ha colpito il pulsante di invio ottengo l'errore: {"The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated."} Tutte le idee che è il problema? Suppongo che il metodo di modifica stia cercando di aggiornare il valore pubblicato nel DB alla modifica, ma per qualche motivo non gli piace ... Anche se non vedo perché la data è coinvolta in quanto non è menzionata nel metodo di controllo per la modifica?

+1

'modelBuilder.Entity () .Property (d => d.CurrentTime) .HasColumnType (" datetime2 ");' –

risposta

146

Il problema è che si sta usando ApplyPropertyChanges con un oggetto modello che è stato compilato solo con dati nel modulo (titolo, storia e immagine). ApplyPropertyChanges applica le modifiche a tutte le proprietà dell'oggetto, incluso lo DateTime non inizializzato, impostato su 0001-01-01, che non rientra nell'intervallo di SQL Server DATETIME.

Anziché utilizzare ApplyPropertyChanges, suggerirei di recuperare l'oggetto da modificare, modificare i campi specifici modificati dal modulo, quindi salvare l'oggetto con tali modifiche; in questo modo, solo i campi modificati vengono modificati. In alternativa, puoi inserire input nascosti nella tua pagina con gli altri campi compilati, ma ciò non sarebbe molto amichevole con modifiche simultanee.

Aggiornamento:

Ecco un campione non testata di soli aggiornare alcuni campi del vostro oggetto (questo è supponendo che si sta utilizzando LINQ to SQL):

var story = _db.ArticleSet.First(a => a.storyId == ArticleToEdit.storyId); 
story.headline = ArticleToEdit.headline; 
story.story = ArticleToEdit.story; 
story.image = ArticleToEdit.image; 
story.modifiedDate = DateTime.Now; 
_db.SubmitChanges(); 
+0

Molto utile :) Mi stavo chiedendo perché la data fosse modificata quando non l'avevo specificata. Puoi aiutare a cambiare il metodo Edit quindi non usa più ApplyPropertyChanges? Dato che sono nuovo di ASP.NET e non lo capisco completamente al momento. Grazie amico. – Cameron

+0

Cosa succede se volessi impostare la data sulla data corrente, ad es. il datetime che l'articolo è stato aggiornato? Probabilmente questa sarà l'opzione migliore e presumo che funzionerà con il ApplyPropertyChanges che ho in gioco. – Cameron

+0

Vedere la mia modifica (presuppone che 'modifiedDate' è il nome della proprietà) – Jacob

31

DATETIME supports 1753/1/1 to "eternity" (9999/12/31), while DATETIME2 support 0001/1/1 through eternity.

Msdn

Risposta: Suppongo che si tenta di salvare DateTime con '0001/1/1' valore. Basta impostare breakpoint ed eseguire il debug, se è vero che sostituire DateTime con una data normale nullo o impostata.

+0

Cosa devo inserire nel controller? Il debug mostra solo l'errore che ho postato sopra. Grazie. – Cameron

+0

sembra errore qui -> _db.SaveChanges(); È possibile impostare il punto di interruzione prima di questa linea ... –

+0

Sì, sì. Quindi si dice che si tratta di un errore su SaveChanges, quindi guardo InnerException e dice che è a causa dell'errore pubblicato, quindi questo è l'errore! – Cameron

7

Se si dispone di una colonna che è datetime e consente null si otterrà questo errore. Consiglio di impostare un valore per passare all'oggetto prima di .SaveChanges();

13

Questo mi stava facendo impazzire. Volevo evitare di utilizzare una dataend Nullabile (DateTime?). Non avevo la possibilità di utilizzare il tipo datetime2 di SQL 2008 (modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2");).

alla fine ho optato per il seguente:

public class MyDb : DbContext 
{ 
    public override int SaveChanges() 
    { 
     UpdateDates(); 
     return base.SaveChanges(); 
    } 

    private void UpdateDates() 
    { 
     foreach (var change in ChangeTracker.Entries<MyEntityBaseClass>()) 
     { 
      var values = change.CurrentValues; 
      foreach (var name in values.PropertyNames) 
      { 
       var value = values[name]; 
       if (value is DateTime) 
       { 
        var date = (DateTime)value; 
        if (date < SqlDateTime.MinValue.Value) 
        { 
         values[name] = SqlDateTime.MinValue.Value; 
        } 
        else if (date > SqlDateTime.MaxValue.Value) 
        { 
         values[name] = SqlDateTime.MaxValue.Value; 
        } 
       } 
      } 
     } 
    } 
} 
94

Questo è un errore comune gente faccia quando si utilizza Entity Framework. Ciò si verifica quando l'entità associata alla tabella che si sta salvando ha un campo datetime obbligatorio e non lo si imposta con qualche valore.

L'oggetto datetime predefinito viene creato con un valore di 01/01/1000 e verrà utilizzato al posto di null. Questo verrà inviato alla colonna datetime che può contenere i valori di data da 1753-01-01 00:00:00 in poi, ma non prima, portando all'eccezione fuori range.

Questo errore può essere risolto modificando il campo del database per accettare null o inizializzando il campo con un valore.

+2

Ciò si verifica quando il campo data/ora nel database è facoltativo e il valore non è impostato. Pertanto, non si tratta di persone comuni errore questo è uno dei problemi di architettura EF. –

+0

Sono d'accordo che EF dovrebbe vedere il tipo in DB e regolare di conseguenza o lanciare o almeno lanciare un errore più preciso. Sul lato positivo, mi piace la tua risposta dal momento che hai fornito 2 opzioni invece del solito - inizializza il file con il valore minimo. – DanteTheSmith

3

Nel mio caso, nell'inizializzatore della classe che stavo usando nella tabella del database, non stavo impostando alcun valore predefinito per la mia proprietà DateTime, quindi risultante nel problema spiegato nella risposta di @Andrew Orsich. Quindi ho solo reso la proprietà nullable. Oppure avrei potuto dargli anche DateTime.Now nel costruttore. Spero che aiuti qualcuno.

1

Inoltre, se non si conosce parte del codice in cui si è verificato un errore, è possibile eseguire il profilo dell'esecuzione sql "non valida" utilizzando sql profiler integrato in mssql.

Bad datetime param verranno visualizzati qualcosa di simile:

bad param

4

ho ottenuto questo errore dopo ho cambiato il mio modello (primo codice) come segue:

public DateTime? DateCreated 

a

public DateTime DateCreated 

Le righe presenti con valore null in DateCreated hanno causato thi errore s. Quindi ho dovuto usare manualmente SQL UPDATE Statement per inizializzare il campo con un valore standard.

Un'altra soluzione potrebbe essere una specifica del valore predefinito per il file.

2

Sembra che si stia utilizzando il framework di entità. La mia soluzione era quella di passare tutte le colonne datetime a datetime2 e usare datetime2 per qualsiasi nuova colonna, in altre parole rendere EF utilizzare datetime2 per impostazione predefinita. Aggiungere questo al metodo OnModelCreating sul contesto:

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2")); 

che otterrà tutte le DateTime e DateTime? proprietà su tutte le entità nel modello.

4

È inoltre possibile risolvere questo problema aggiungendo al modello (versione Entity Framework> = 5)

[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
public DateTime CreationDate { get; set; } 
0

provare a fare l'annullabile proprietà.

public DateTime? Time{ get; set; } 

Ha funzionato per me.

0

Se ahve accesso al DB, è possibile modificare il tipo di colonna DB da datetime a datetime2 (7) sarà ancora inviare un oggetto datetime e sarà salvato

1

Ho avuto lo stesso problema, purtroppo , Ho due proprietà DateTime sul mio modello e una proprietà DateTime è null prima di fare SaveChanges.

Quindi assicuratevi che il modello ha valore DateTime prima di salvare le modifiche o renderlo annullabile per evitare l'errore:

public DateTime DateAdded { get; set; } //This DateTime always has a value before persisting to the database. 
public DateTime ReleaseDate { get; set; } //I forgot that this property doesn't have to have DateTime, so it will trigger an error 

Quindi questo risolve il problema, è una questione di rendere sicuro il vostro data di modello è corretto prima di persistente a il database:

public DateTime DateAdded { get; set; } 
public DateTime? ReleaseDate { get; set; } 
0

Il modello deve disporre di un valore di datetime nullable. Al posto di ApplyPropertyChanges dovrebbe essere utilizzato il metodo suggerito in precedenza per recuperare l'oggetto che deve essere modificato. Nel mio caso ho avuto questo metodo per salvare il mio oggetto:

public ActionResult Save(QCFeedbackViewModel item) 

E poi in servizio, posso recuperare usando:

RETURNED = item.RETURNED.HasValue ? Convert.ToDateTime(item.RETURNED) : (DateTime?)null 

Il codice completo del servizio è il seguente:

var add = new QC_LOG_FEEDBACK() 
      { 

       QCLOG_ID = item.QCLOG_ID, 
       PRE_QC_FEEDBACK = item.PRE_QC_FEEDBACK, 
       RETURNED = item.RETURNED.HasValue ? Convert.ToDateTime(item.RETURNED) : (DateTime?)null, 
       PRE_QC_RETURN = item.PRE_QC_RETURN.HasValue ? Convert.ToDateTime(item.PRE_QC_RETURN) : (DateTime?)null, 
       FEEDBACK_APPROVED = item.FEEDBACK_APPROVED, 
       QC_COMMENTS = item.QC_COMMENTS, 
       FEEDBACK = item.FEEDBACK 
      }; 

      _context.QC_LOG_FEEDBACK.Add(add); 
      _context.SaveChanges(); 
Problemi correlati