实体框架将 DateTimeOffset 映射到 SQL Server DateTime

Posted

技术标签:

【中文标题】实体框架将 DateTimeOffset 映射到 SQL Server DateTime【英文标题】:Entity Framework Mapping DateTimeOffset to SQL Server DateTime 【发布时间】:2012-03-12 11:52:53 【问题描述】:

有没有办法将 DateTimeOffset 属性映射到 SQL Server datetime 列,假设您不能更改任何一方,这意味着属性和列必须保持这些日期类型?

我知道最简单的方法是让它们匹配,但想知道是否有办法解决这个问题。我正在研究自定义映射,但似乎我必须自己映射所有列,而不仅仅是 DateTimeOffset 属性。

我试过了:

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

但这引发了Member Mapping specified is not valid 错误。

我希望能够将 UtcDateTime DateTimeOffset 属性值放入数据库中,并且在读取时将 DateTimeOffset 设为 UTC(即偏移为零)。

【问题讨论】:

【参考方案1】:

没有。 .NET 类中的DateTimeOffset 将映射到DateTimeOffset SQL 类型。您不能直接更改此行为,因为 EF 不提供简单的类型转换/映射。如果你想将它存储为DateTime,你必须破解它。

首先定义 Customer 类,使用技巧将私有属性暴露给 @cincura.net 在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; 

现在您有两个属性 - 一个是私有的并持有您想要持久保存到数据库的 DataTime,另一个是公开的为您的应用程序公开 DateTimeOffset。在您的上下文中定义它:

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

无论如何你为什么不直接使用DateTime并将其存储在UTC?

【讨论】:

感谢您的回复。我们必须使用多个时区,并且使用 DateTimeOffset 进行算术比在对时间进行任何算术之前必须将所有内容转换为 UTC 更容易。 使用 EF 避免 DateTime 的一个原因是值不会往返:所有值都使用 DateTimeKind.Unspecified 加载。无法告诉 EF 它应该默认为 UTC。当然有一些技巧可以修复它,但它们很丑陋,有些可能会损害性能(使用 ObjectContext 事件)。 @SørenBoisen - 在创建表期间的迁移中,我只需添加 defaultValueSql: "GETUTCDATE()" 完整示例:CreatedDate = c.DateTime(nullable: false, precision: 7, storeType: "datetime2", defaultValueSql: "GETUTCDATE()"),

以上是关于实体框架将 DateTimeOffset 映射到 SQL Server DateTime的主要内容,如果未能解决你的问题,请参考以下文章

不存在从 DbType System.DateTimeOffset 到已知 SqlCeType 的映射

实体框架将集合属性映射到一列

如何使用实体框架将字符串映射到 Uri 类型?

将关系映射到实体框架中的抽象集合

实体框架 - 您能否将导入的存储过程的结果类型映射到自定义实体类型?

将 SQL Server tinyint 映射到 Int16 的实体框架