La memorizzazione del Tempo con Entity Framework Codefirst – SqlDbType.Tempo di overflow

Sto cercando di seme di alcune costanti nel mio DB:

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 è dentro il mio Seme() funzione per EF Codefirst Migrazioni. Non riesce a Palco Otto con le seguenti:

Sistema.Dati.UpdateException: si è verificato Un errore durante l’aggiornamento del
non valide. Vedere l’interno eccezione per i dettagli. —>
Sistema.OverflowException: SqlDbType.Tempo di overflow. Valore ‘1.00:00:00’
è fuori portata. Deve essere compreso tra 00:00:00.0000000 e
23:59:59.9999999.

Perché non essere in grado di memorizzare un arco con EF? Spero davvero non ho bisogno di fare un po ‘ sciocco time-to-zecche conversione su entrambe le estremità qui…

InformationsquelleAutor SB2055 | 2013-06-16



3 Replies
  1. 7

    In questa riga:

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

    Si sta utilizzando questo costruttore:

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

    Così sei in realtà la creazione di un TimeSpan maggiore di 24 ore dal momento che si sta passando 1 per il days parametro, mentre il Database sottostante è di tipo Time che accetta solo valori compresi tra 00:00 e le 23:59.

    Difficile dire se effettivamente si vuole avere una TimeSpan con 1 giorno, o è solo un errore di battitura.

    Se si vuole veramente un TimeSpan maggiore di 24 ore, credo che dovrete mappa del campo a un altro tipo di Database (come SmallDateTime).

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

    Span = new TimeSpan(1, 0, 0),
    • Da quando non è un logico periodo di tempo limitato a 24 ore? Soprattutto stupido come il TimeSpan classe supporta più giorni.
    • Da nessuna parte nella risposta si dice che è TimeSpan che è limitata per 24 ore, è mappata colonna di database (Time) che è limitato. È tutto sbagliato mappatura, non TimeSpan limitazione (che è sicuramente il supporto per più di 1 giorno).
    • Esattamente. Il DB tipo di mappatura è semplicemente sbagliato, come TimeSpan dati non ft in un db tipo Time. Questo suona come un bug.
    • Sì, Timespan può tenere anni e secoli, sicuramente un bug nel modo in cui EF mappe. – Forse c’è un modo per impostare la dimensione del campo con un attributo in EF?
    • SmallDateTime NON è una buona soluzione. Io suggerisco di usare BIGINT di conservarla come “Zecche” (a lungo).
  2. 33
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete("Property '" + nameof(Duration) + "' should be used instead.")]        
        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
        }

    Aggiornamento

    Questo è oggi ottenibile dal EF Core 2.1, utilizzando Conversione Del Valore Di.

    builder.Entity<Stage>()
        .Property(s => s.Span)
        .HasConversion(new TimeSpanToTicksConverter()); //or TimeSpanToStringConverter
    • Grande risposta, potrebbe essere la pena di aggiungere un [NotMapped] attributo di Durata
    • Questo potrebbe essere utile per coloro perplesso da pragma avviso di soppressione: stackoverflow.com/questions/968293/…
    • Brent, in realtà se si aggiunge il [NotMapped] attributo per la Durata, la colonna sarà caduto, che cancellerà tutti i dati presenti nella colonna e DurationTicks colonna contiene 0.
    • Ciao commentatori, non si può capire come sia arrivato omesso dalla mia risposta, ma sì, si dovrebbe naturalmente essere lì.
    • noi in realtà NON vuole essere riflessa al database, noi vogliamo che le zecche di essere lì.
    • guardare fuori HasConversion<TimeSpanToTicksConverter>(); è non il modo giusto per registrare il convertitore! è necessario passare un esempio, invece dei generici tipo come questo: HasConversion(new TimeSpanToTicksConverter());
    • Yep. I generici genera un errore durante le migrazioni. L’istanza di base di uno non.
    • Grazie per l’aggiornamento

  3. 1

    Il problema, come accennato in precedenza, è il fatto che EF mappe TimeSpan classe a Tempo, che è limitata a 24 ore.

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

    1) Creare un Arco entità con int proprietà per i diversi elementi di un tempo, 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; }
    }

    Semplicemente aggiungere straniera di riferimento, nel caso di entità personalizzata Timespan entità.

    2) Fare qualche sciocco time-to-zecche di conversione, come spiegato in questo post del blog.

    • Opzione 2 è molto meno stupido rispetto all’opzione 1, che è solo uno spreco di spazio su disco. 304 Bit invece che a 64 Bit? Pazzesco… 🙂
    • Non c’è la “conversione” tra TimeSpan e long, TimeSpan è già un long, è internamente salvati in questo modo, vedere per se stessi.

Lascia un commento