NodaTime如何与EF Code First一起使用?

sma*_*dev 28 entity-framework nodatime

我真的希望能够在我的Entity Framework Code First数据库项目中使用NodaTime,但还没有找到一种"干净"的方法来实现它.我真正想做的是:

public class Photoshoot
{
    public Guid PhotoshootId{get; set;}
    public LocalDate ShootDate{get; set;} //ef ignores this property
}
Run Code Online (Sandbox Code Playgroud)

是否有任何支持或推荐的方法将NodaTime与EF Code First一起使用?

Mat*_*ton 19

在实体框架中本机支持自定义基元类型持久性之前,常见的解决方法是使用伙伴属性.

对于域模型中的每个自定义基元,您可以创建关联的映射基元,以便以Entity Framework支持的格式保存值.然后根据其对应的伙伴属性的值计算自定义原始属性.

例如:

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 }
    }
}
Run Code Online (Sandbox Code Playgroud)

我们在代码中使用NodaTime,首先使用这种方法POCO.

显然,这会使您只使用一种类型作为代码优先POCO和域类型.这可以通过将不同的职责分成两种类型并在它们之间进行映射来以牺牲复杂性为代价来改进.中途替代方案是将域属性推送到子类型并使所有映射的伙伴属性受到保护.使用一定数量的wanging Entity Framework可以映射到受保护的属性.

这篇相当精彩的博客文章评估了Entity Framework对各种域建模构造的支持,包括封装的原语.这是我在设置POCO时最初找到伙伴属性的概念:http: //lostechies.com/jimmybogard/2014/04/29/domain-modeling-with-entity-framework-scorecard/

该系列中的另一篇博客文章讨论了映射到受保护属性:http://lostechies.com/jimmybogard/2014/05/09/missing-ef-feature-workarounds-encapsulated-collections/


Col*_*ern 11

没有"干净"的方式,我知道,因为在撰写本文时,EF 没有像NHibernate(IUserType)中看到的简单类型转换机制.作为ORM的EF的真正限制导致我改变我的域以适合我的ORM.


Che*_*hen 9

EF Core 2.1有一个新功能Value Conversions,它正是针对这种情况.

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

.HasConversion有一些其他重载使这个逻辑可以重复使用,例如你可以定义自己的ValueConverter.

  • 这种方法有一个严重的缺点:EFCore到目前为止无法比较使用ValueConvertor在数据存储区(至少是SQL)映射的自定义类型值(因此至少将其加载到内存中并进行过滤)。参见https://github.com/aspnet/EntityFrameworkCore/issues/11156 (2认同)