Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Mapping DateTimeOffset to SQL Server DateTime

Is there a way to map a DateTimeOffset property to a SQL Server datetime column, with the assumption that you can't change either side, meaning that the property and column have to stay those date types?

I know the easiest is to make them match but want to know if there's a way to work around this. I was looking into custom mappings but it seemed like I had to map all of the columns myself and not just the DateTimeOffset property.

I tried:

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

But that threw the Member Mapping specified is not valid error.

I was hoping to be able to put the UtcDateTime DateTimeOffset property value in the DB and when reading have the DateTimeOffset be in UTC (i.e. have an Offset of zero).

like image 804
Carlos Avatar asked Feb 22 '12 06:02

Carlos


People also ask

Why use DateTimeOffset instead of DateTime?

With its Kind property, DateTime is able to reflect only Coordinated Universal Time (UTC) and the system's local time zone. DateTimeOffset reflects a time's offset from UTC, but it doesn't reflect the actual time zone to which that offset belongs.

What is the difference between DateTime and Datetimeoffset?

Perhaps the most obvious difference is that the datetimeoffset stores the time zone offset, whereas datetime doesn't. Another important difference is that datetimeoffset allows you to specify the precision (up to 7 decimal places).

What is Datetimeoffset data type?

The DATETIMEOFFSET data type is a date and time with time zone awareness. DATETIMEOFFSET supports dates from 0001-01-01 through 9999-12-31. The default value is 1900-01-01 00:00:00 00:00. The time is based on 24-hour UTC clock.


1 Answers

No. DateTimeOffset in .NET class will map to DateTimeOffset SQL type. You cannot change this behavior directly because EF doesn't provide simple type conversions / mappings. If you want to store it as DateTime you must hack it.

First define Customer class with trick to expose private property to mapping referenced by @cincura.net in 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; }
}

Now you have two properties - one is private and holds DataTime which you want to persist to database and one is public exposing DateTimeOffset for your application. Define it in your context:

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

Anyway why you don't use DateTime directly and store it in UTC?

like image 185
Ladislav Mrnka Avatar answered Sep 21 '22 18:09

Ladislav Mrnka