2013-10-09 97 views
3

我有一個大型的數據庫,我們做了很多TimeZone轉換。我正在慢慢地將數據庫轉換爲使用DateTimeOffSet數據類型,但這是我無法做到的。太多的變化。我可以在EF中將DateTime的SQL DataType轉換爲DateTimeOffSet嗎?

但是我可以改變代碼,因爲我知道我的所有日​​期都存儲在數據庫中的UTC,所以我想在.NET中使用DateTimeOffSet對象。

我怎樣才能讓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 - 如果我遵循該線程中接受的答案,我會得到一個新的錯誤:「屬性'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); 
    } 
} 

現在任何DateTimeDateTime?屬性,你可以把這個屬性:

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

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

有了這個地方,只要實體框架加載實體從數據庫中,它將設置您指定的DateTimeKind,例如UTC。

現在,你說你想開始切換到DateTimeOffset類型。您可以利用DateTime具有單向隱式轉換爲DateTimeOffset的事實,該轉換將考慮.Kind。換句話說,你可以這樣做:

DateTimeOffset BarDTO = foo.Bar; 

即使foo.BarDateTime,這將工作。由於該種類設置爲UTC,因此在DateTimeOffset中的偏移量將設置爲零。

當然,你總是可以像這樣的東西做在你的模型:

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

我相信你能想出這一變化,以滿足您的需求。主要的是,無論屬性映射到字段,類型必須匹配。

+0

不是*正確*我正在爲之奮鬥,但向着正確的方向邁出了可觀的一步。 – Russ

相關問題