2013-06-16 22 views
17

Sto cercando di seminare alcune costanti nel mio DB:Memorizzazione TimeSpan con Entity Framework Codefirst - SqlDbType.Time trabocco

context.Stages.AddOrUpdate(s => s.Name, 
            new Stage() 
            { 
             Name = "Seven", 
             Span = new TimeSpan(2, 0, 0), 
             StageId = 7 
            }); 
context.Stages.AddOrUpdate(s => s.Name, 
            new Stage() 
            { 
             Name = "Eight", 
             Span = new TimeSpan(1, 0, 0, 0), 
             StageId = 8 
            }); 

Questo è nel mio Seed (funzione) per EF Codefirst Migrazioni. Non riesce a fase Otto con il seguente:

System.Data.UpdateException: Si è verificato un errore durante l'aggiornamento delle voci. Vedi l'eccezione interna per i dettagli. ---> System.OverflowException: SqlDbType.Time overflow. Valore '1.00: 00: 00' non compreso nell'intervallo. Deve essere compreso tra 00: 00: 00.0000000 e 23: 59: 59.9999999.

Perché non riuscire a memorizzare un intervallo di tempo utilizzando EF? Spero davvero che non ho bisogno di fare un po di conversione stupido time-to-zecche su entrambe le estremità qui ...

risposta

5

In questa linea:

Span = new TimeSpan(1, 0, 0, 0) 

Stai usando questo costruttore:

public TimeSpan(int days, int hours, int minutes, int seconds); 

Così si sta effettivamente creando un TimeSpan superiore a 24 ore da quando si sta passando 1 al parametro days, mentre il tipo di database sottostante è Time che accetta solo valori compresi tra 00: 00-23: 59.

Difficile dire se effettivamente si intende avere un TimeSpan con 1 giorno, o è solo un refuso.

Se si vuole veramente una TimeSpan superiore alle 24 ore, credo si dovrà mappare il campo ad un altro tipo di database (come SmallDateTime).

Se è solo un errore di battitura, basta cambiare la vostra linea a:

Span = new TimeSpan(1, 0, 0), 
+5

Da quando è un intervallo logico limitato a 24 ore? Particolarmente sciocco come la classe 'TimeSpan' [supporta più giorni] (https://msdn.microsoft.com/en-us/library/85ydwftb%28v=vs.110%29.aspx). – Diederik

+1

@Diederik, da nessuna parte nella risposta si dice che è 'TimeSpan' che è limitato a 24 ore, è la colonna del database mappato (' Time') che è limitata.Si tratta di una mappatura errata, non di una limitazione di 'TimeSpan' (che supporta sicuramente più di 1 giorno). – haim770

+7

Esattamente. La mappatura del tipo di DB è semplicemente sbagliata, dato che i dati di "TimeSpan" non sono in un "db" di tipo db. Sembra un bug. – Diederik

2

Il problema, come accennato in precedenza, è il fatto che EF associa la classe TimeSpan a Time, che è limitata a 24 ore.

Se avete bisogno di memorizzare un periodo superiore a 24 ore, vorrei suggerire una delle due seguenti approcci:

1) creare un'entità TimeSpan con proprietà int per i diversi elementi di un periodo, qualcosa come:

public class Timespan 
{ 
    public Int64 Id { get; set; } 

    public Int16 Years { get; set; } 

    public int Months { get; set; } 

    public Int64 Days { get; set; } 

    public Int64 Hours { get; set; } 

    public Int64 Minutes { get; set; } 
} 

Basta aggiungere un riferimento esterno nell'entità applicabile all'entità di periodo di tempo personalizzato.

2) Effettua una conversione stupida time-to-ticks, come spiegato in questo blog post.

+3

L'opzione 2 è molto meno stupida dell'opzione 1, che è solo uno spreco di spazio su disco. 304 bit anziché 64 bit? Insane ... :) –

+0

Non c'è alcuna "conversione" tra 'TimeSpan' e' long', 'TimeSpan' ** è ** già un' long', è memorizzato internamente in questo modo, [vedi tu stesso] (http : //referencesource.microsoft.com/#mscorlib/system/timespan.cs,97). – Shimmy

21
[Obsolete("Property 'Duration' should be used instead.")] 
    [Browsable(false)] 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    public long DurationTicks { get; set; } 

    [NotMapped] 
    public TimeSpan Duration 
    { 
#pragma warning disable 618 
     get { return new TimeSpan(DurationTicks); } 
     set { DurationTicks = value.Ticks; } 
#pragma warning restore 618 
    } 
+2

Ottima risposta, potrebbe valere la pena aggiungere un attributo [NotMapped] a Durata – Brent

+3

Ciò potrebbe essere utile per chi è perplesso dalla soppressione degli avvisi pragma: http://stackoverflow.com/questions/968293/c-sharp-selectively-suppress-custom- obsoleto-warnings –

+0

Brent, in realtà se si aggiunge l'attributo [NotMapped] alla colonna Duration, la colonna verrà eliminata, che cancellerà tutti i dati esistenti in questa colonna e la colonna DurationTicks conterrà 0. – Artemious

Problemi correlati