2012-02-22 9 views
5

Czy istnieje sposób odwzorowania właściwości DateTimeOffset na kolumnę SQL Server datetime z założeniem, że nie można zmienić żadnej ze stron, co oznacza, że ​​właściwość i kolumna muszą pozostać tą datą typy?Mapowanie jednostek Entity DataTimeOffset na SQL Server DataTime

Wiem, że najłatwiej jest je dopasować, ale chcą wiedzieć, czy istnieje sposób obejścia tego problemu. Szukałem niestandardowych mapowań, ale wydawało mi się, że muszę sam zamapować wszystkie kolumny, a nie tylko właściwość DateTimeOffset.

Próbowałem:

modelBuilder.Entity<Customer>().Property(c => c.LastModifiedOn).HasColumnType("datetime"); 

Ale że wyrzucił błąd Member Mapping specified is not valid.

Miałem nadzieję, że będę w stanie umieścić wartość właściwości UtcDateTime DateTimeOffset w db i podczas odczytu mieć wartość UTC (tj. Mieć Offset równy zero).

Dzięki.

Odpowiedz

12

Numer DateTimeOffset w klasie .NET zostanie odwzorowany na typ SQL SQL DateTimeOffset. Nie można zmienić tego zachowania bezpośrednio, ponieważ EF nie zapewnia prostych konwersji/odwzorowań typów. Jeśli chcesz go zapisać jako DateTime, musisz go zhackować.

pierwsze zdefiniować klasę Klientowi sztuczki, aby odsłonić własność prywatną do mapowania odwołuje @ cincura.net w this post:

public class Customer 
{ 
    public static class CustomerExpressions 
    { 
     public static readonly Expression<Func<Customer, DateTime>> LastModifiedOn = c => c.LastModifiedOnInternal; 
    } 

    // Other properties 

    public DateTimeOffset LastModifiedOn 
    { 
     get { return new DateTimeOffset(LastModifiedOnInternal); } 
     set { LastModifiedOnInternal = value.DateTime; } 
    } 

    private DateTime LastModifiedOnInternal { get; set; } 
} 

Teraz masz dwie właściwości - jeden jest prywatny i posiada DataTime którego chcesz utrzymują się baza danych i jedna jest publiczna, podając do swojej aplikacji numer DateTimeOffset. Zdefiniuj go w kontekście:

public class Context : DbContext 
{ 
    public DbSet<Customer> Customers { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Customer>().Ignore(c => c.LastModifiedOn); 
     modelBuilder.Entity<Customer>().Property(Customer.CustomerExpressions.LastModifiedOn).HasColumnName("LastModifiedOn"); 
    } 
} 

Zresztą dlaczego nie używasz DateTime bezpośrednio i przechowywać go w UTC?

+0

Dzięki za odpowiedź. Musimy pracować z wieloma strefami czasowymi, a robienie arytmetyki przy pomocy funkcji DateTimeOffset jest łatwiejsze niż konwersja wszystkiego na UTC przed wykonaniem arytmetyki z czasami. – Carlos

+4

Jedną z przyczyn uniknięcia DateTime z EF jest to, że wartości nie są okrągłe: wszystkie wartości są załadowane za pomocą DateTimeKind.Unspecified. Bez możliwości powiedzenia EF, że powinien domyślnie UTC. Na pewno są hacki do naprawienia, ale są brzydkie, a niektóre mogą zaszkodzić wydajności (używając zdarzeń ObjectContext). –

+0

@ SørenBoisen - Podczas mojej migracji podczas tworzenia tabeli, po prostu dodaję "defaultValueSql:" GETUTCDATE() "' – Suamere