How can NodaTime be used with EF Code First?

风格不统一 提交于 2019-11-27 17:52:00

Until custom primitive type persistence is natively supported in Entity Framework, a common work around is to use buddy properties.

For each custom primitive within your domain model, you create an associated mapped primitive to hold the value in a format supported by Entity Framework. The custom primitive properties are then calculated from the value of their corresponding buddy property.

For example:

public class Photoshoot
{
    // mapped
    public Guid PhotoshootId{get; set;}

    // mapped buddy property to ShootDate
    public DateTime ShootDateValue { get; set; }

    // non-mapped domain properties
    public LocalDate ShootDate 
    {
        get { // calculate from buddy property }
        set { // set the buddy property }
    }
}

We use NodaTime in our code first POCO's using exactly this approach.

Obviously this leaves you with a single type acting as both a code first POCO and a domain type. This can be improved at the expense of complexity by separating out the different responsibilities into two types and mapping between them. A half-way alternative is to push the domain properties into a subtype and make all mapped buddy properties protected. With a certain amount of wanging Entity Framework can be made to map to protected properties.

This rather splendid blog post evaluates Entity Framework support for various domain modelling constructs including encapsulated primitives. This is where I initially found the concept of buddy properties when setting up our POCO's: http://lostechies.com/jimmybogard/2014/04/29/domain-modeling-with-entity-framework-scorecard/

A further blog post in that series discusses mapping to protected properties: http://lostechies.com/jimmybogard/2014/05/09/missing-ef-feature-workarounds-encapsulated-collections/

No "clean" way that I'm aware of because EF, as of this writing, doesn't have a mechanism for simple type conversion like you see in NHibernate (IUserType). A real limitation in EF as an ORM which causes me to change my domain to suit my ORM.

EF Core 2.1 has a new feature Value Conversions, which is exactly for this scenario.

//OnModelCreating
builder.Entity<MyEntity>
       .Property(e => e.SomeInstant)
       .HasConversion(v => v.ToDateTimeOffset(), v => Instant.FromDateTimeOffset(v));

.HasConversion has some other overloads to make this logic re-useable, for example you can define your own ValueConverter.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!