2013-06-16 7 views
17

Próbuję nasion pewne stałe do mojego DB:Przechowywanie TimeSpan z Entity Framework Codefirst - SqlDbType.Time przelewowy

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 
            }); 

To w moim nasieniu function() dla EF Codefirst migracje. Nie powiedzie się na etapie ósmym:

System.Data.UpdateException: Wystąpił błąd podczas aktualizowania wpisów . Zobacz wewnętrzny wyjątek, aby poznać szczegóły. ---> System.OverflowException: SqlDbType.Time przepełnienie. Wartość "1,00: 00: 00" jest poza zakresem. Musi być między 00: 00: 00.0000000 a 23: 59: 59.9999999.

Dlaczego nie można zapisać przedziału czasowego za pomocą EF? Mam nadzieję, że nie muszę robić jakieś głupie czas do kleszczy konwersję na obu końcach tutaj ...

Odpowiedz

5

W tej linii:

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

używasz tego konstruktora:

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

Więc faktycznie tworząc TimeSpan większy niż 24 godzin od momentu jesteś przejazdem 1 do parametru days, podczas gdy twój bazowy typ bazy danych jest Time który przyjmuje tylko wartości między 00: 00-23: 59.

Trudno powiedzieć, czy rzeczywiście chciałeś mieć TimeSpan z 1 dniem, czy to tylko literówka.

Jeśli naprawdę chcesz TimeSpan więcej niż 24 godziny, domyślam się, że będziesz musiał zamapować swoje pole na inny typ bazy danych (np. SmallDateTime).

Jeśli to tylko błąd literówka, tylko zmienić linię:

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

Od kiedy to logiczny czas ograniczony do 24 godzin? Szczególnie głupi jak klasa "TimeSpan" [obsługuje wiele dni] (https://msdn.microsoft.com/en-us/library/85ydwftb%28v=vs.110%29.aspx). – Diederik

+1

@Diederik, Nigdzie w odpowiedzi nie mówi, że jest to "TimeSpan", który jest ograniczony do 24 godzin, to zmapowana kolumna bazy danych ('Time') jest ograniczona.Chodzi o złe mapowanie, a nie ograniczenie "TimeSpan" (to zdecydowanie więcej niż 1 dzień). – haim770

+7

Dokładnie. Mapowanie typu DB jest po prostu niepoprawne, ponieważ dane 'TimeSpan' nie zawierają danych typu db' Time'. To brzmi jak błąd. – Diederik

2

Problem, jak wcześniej wspomniano, jest fakt, że EF odwzorowuje klasę TimeSpan do czasu, który jest ograniczony do 24 godzin.

Jeśli trzeba zapisać żądany przedział czasu większy niż 24 godzin, chciałbym zaproponować jedną z dwóch następujących metod:

1) utworzyć osobę TimeSpan o właściwościach int dla różnych elementów przedziale czasu, coś takiego:

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; } 
} 

Po prostu dodaj obce referencje w odpowiednim podmiocie do niestandardowego elementu Przedział czasu.

2) Wykonaj jakąś głupią konwersję czasu na kleszcze, jak wyjaśniono w tym blog post.

+3

Opcja 2 jest znacznie mniej głupie niż opcja 1, co jest tylko marnowaniem miejsca na dysku. 304 Bit zamiast 64 bitów? Szalony ... :) –

+0

Nie ma "konwersji" pomiędzy 'TimeSpan' i' long', 'TimeSpan' ** jest ** już' long', jest przechowywany wewnętrznie w ten sposób, [sam sprawdź] (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

Świetna odpowiedź, może warto dodać atrybut [NotMapped] do Duration – Brent

+3

Może to być pomocne dla osób zaintrygowanych ostrzeżeniem o pragma: http://stackoverflow.com/questions/968293/c-sharp-selectively-suppress-custom- przestarzałe ostrzeżenia –

+0

Brent, jeśli dodasz atrybut [NotMapped] do kolumny Czas trwania, kolumna zostanie usunięta, co spowoduje usunięcie wszystkich istniejących danych w tej kolumnie, a kolumna DurationTicks będzie zawierać 0. – Artemious