2013-10-09 4 views
3

У меня есть большая база данных, где мы делаем много конверсий TimeZone. Я медленно конвертирую базу данных для использования типов данных DateTimeOffSet, но это то, что я не могу сделать на борту. Слишком много изменений.Можно ли преобразовать SQL DataType DateTime в DateTimeOffSet в EF?

Я могу изменить код, и, поскольку я знаю, что все мои даты хранятся в UTC в базе данных, я хотел бы просто использовать объект DateTimeOffSet в .NET.

Как я могу получить EF для преобразования на лету для меня?

Я попытался это:

modelBuilder.Properties<DateTimeOffset>() 
       .Configure(c => c.HasColumnType("datetime")); 

Но я получаю ошибку

(37,12) : error 2019: Member Mapping specified is not valid. The type 'Edm.DateTimeOffset[Nullable=True,DefaultValue=,Precision=]' of member 'ModifyDate' in type '{ObjectType}' is not compatible with 'SqlServer.datetime[Nullable=True,DefaultValue=,Precision=3]' of member 'ModifyDate' in type 'CodeFirstDatabaseSchema.{ObjectType}'.

+0

simular question http://stackoverflow.com/questions/9389954/entity-framework-mapping-datetimeoffset-to-sql-server-datetime –

+0

@ArsenMrkt - Если я следую принятому ответу в этой теме, я получаю новый error: «Свойство CreateDate не является объявленным свойством в типе« {ObjectType} ». Убедитесь, что свойство не было явно исключено из модели с помощью аннотации Ignore или NotMappedAttribute. Убедитесь, что он действителен примитивное свойство ". – Russ

ответ

5

Вот один подход можно рассмотреть:

Во-первых, определить это следующий атрибут:

[AttributeUsage(AttributeTargets.Property)] 
public class DateTimeKindAttribute : Attribute 
{ 
    private readonly DateTimeKind _kind; 

    public DateTimeKindAttribute(DateTimeKind kind) 
    { 
     _kind = kind; 
    } 

    public DateTimeKind Kind 
    { 
     get { return _kind; } 
    } 

    public static void Apply(object entity) 
    { 
     if (entity == null) 
      return; 

     var properties = entity.GetType().GetProperties() 
      .Where(x => x.PropertyType == typeof(DateTime) || x.PropertyType == typeof(DateTime?)); 

     foreach (var property in properties) 
     { 
      var attr = property.GetCustomAttribute<DateTimeKindAttribute>(); 
      if (attr == null) 
       continue; 

      var dt = property.PropertyType == typeof(DateTime?) 
       ? (DateTime?) property.GetValue(entity) 
       : (DateTime) property.GetValue(entity); 

      if (dt == null) 
       continue; 

      property.SetValue(entity, DateTime.SpecifyKind(dt.Value, attr.Kind)); 
     } 
    } 
} 

Теперь подключить этот атрибут до вашего контекста EF:

public class MyContext : DbContext 
{ 
    public DbSet<Foo> Foos { get; set; } 

    public MyContext() 
    { 
     ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += 
      (sender, e) => DateTimeKindAttribute.Apply(e.Entity); 
    } 
} 

Сейчас на любых DateTime или DateTime? свойств, вы можете использовать этот атрибут:

public class Foo 
{ 
    public int Id { get; set; } 

    [DateTimeKind(DateTimeKind.Utc)] 
    public DateTime Bar { get; set; } 
} 

с этим на месте, когда Entity Framework загружает объект из базы данных он установит указанный вами DateTimeKind, например, UTC.

Теперь вы сказали, что хотите переключиться на DateTimeOffset. Вы можете воспользоваться тем фактом, что DateTime имеет одностороннее неявное преобразование в DateTimeOffset, которое учитывает .Kind. Другими словами, вы можете сделать это:

DateTimeOffset BarDTO = foo.Bar; 

Несмотря на то, foo.Bar является DateTime, это будет работать. Поскольку тип установлен в UTC, смещение будет установлено на ноль в DateTimeOffset.

Конечно, вы всегда можете сделать это в вашей модели с чем-то вроде этого:

[NotMapped] 
public DateTimeOffset BarDTO 
{ 
    get { return Bar; } 
    set { Bar = value.UtcDateTime; } 
} 

Я уверен, что вы можете придумать вариации на это в соответствии с вашими потребностями. Главное, что любое свойство сопоставляется с полем, тип должен совпадать.

+0

Не точно * То, что я прыгал, но значительный шаг в правильном направлении. – Russ

Смежные вопросы