【问题标题】:Entity Framework Mapping DateTimeOffset to SQL Server DateTime实体框架将 DateTimeOffset 映射到 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(即偏移为零)。

【问题讨论】:

    标签: entity-framework mapping ef-code-first datetimeoffset


    【解决方案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()"),
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 2017-04-29
    • 1970-01-01
    • 2015-08-17
    • 2010-10-09
    • 1970-01-01
    相关资源
    最近更新 更多