EF Core 2.2中的不同类一对一

时间:2019-02-02 14:22:48

标签: c# asp.net-core entity-framework-core ef-fluent-api

我想跟随this blog解释如何配置一对一关系。它的想法是,一个实体获得另一个类型的属性,而另一个获得前者类型的属性以及一个ID,以创建外键。

但是,我的问题是,我想像这样制动两个不同类的接触部分。 SomeThing 类已经被重构,并且可以与 Address 类一起很好地工作。但是,我不确定如何处理 SomeThingElse 类。

public class SomeThing
{
  public Guid Id { get; set; }
  //public string Street { get; set; }
  //public string City { get; set; }
  public Address Address { get; set; }
}

public class Address
{
  public Guid Id { get; set; }
  public string Street { get; set; }
  public string City { get; set; }
  public Guid SomeThingId { get; set; }
  public SomeThing SomeThing { get; set; }  
}

public class SomeThingElse
{
  public Guid Id { get; set; }
  public string Street { get; set; }
  public string City { get; set; }
  //public Address Address { get; set; }
}

我尝试添加一个专门的类来管理 SomeThingElse 的地址,但是将其分解是没有任何意义的。我考虑过在下面添加两个字段,但由于数据库设计不良而拒绝了这个想法。

public class Address
{
  ...
  public Guid SomeThingElseId { get; set; }
  public SomeThingElse SomeThingElse { get; set; }  
}

最好是一个用于继承的教科书案例,引入了一个基类 Contactable 并完全跳过了 Address 。但是我从前曾记得,继承和EF混合得不好,在这种情况下会有很多麻烦和麻烦。

是否有可靠的最佳做法?当我用Google搜索时,没有发现任何值得信赖的东西。

1 个答案:

答案 0 :(得分:3)

从评论中的讨论中,我将进入详细答案:

您可以使用 EF Core 新引入的Owned Entity类型的功能,其中AddressOwned EntitySomething的{​​{1}}类型SomethingElseSomething是所有者,如下所示:

SomethingElse

按照惯例,EF核心将命名以下的图案为拥有实体类型的属性的数据库中的列的 Navigation_OwnedEntityProperty 。因此,modelBuilder.Entity<SomeThing>().OwnsOne(st => st.Address); modelBuilder.Entity<SomeThingElse>().OwnsOne(st => st.Address); 特性将出现在AddressSomething表的名字 'Address_Street' 和 'ADDRESS_CITY'。

现在,如果您不希望拥有实体类型的列名类似于 Navigation_OwnedEntityProperty ,则可以按以下方式提供自定义列名:

SomethingElse

此外,可以将拥有的类型与所有者存储在单独的表中。为了覆盖将拥有的类型映射到与所有者相同的表的约定,您可以简单地调用modelBuilder.Entity<SomeThing>().OwnsOne(st => st.Address, a => { a.Property(p => p.Street).HasColumnName("Street"); a.Property(p => p.City).HasColumnName("City"); }); modelBuilder.Entity<SomeThingElse>().OwnsOne(ste => ste.Address, a => { a.Property(p => p.Street).HasColumnName("Street"); a.Property(p => p.City).HasColumnName("City"); }); 并提供不同的表名,如下所示:

ToTable

查询拥有的类型

在查询所有者时,默认情况下将包括拥有的类型。即使拥有的类型存储在单独的表中,也不必使用Include方法。

限制

其中一些限制对于拥有实体类型的工作方式至关重要,但另一些限制则是我们可以在将来的版本中删除的限制:

受设计限制:

  • 您不能为拥有的类型创建modelBuilder.Entity<SomeThing>().OwnsOne(st => st.Address, a => { a.ToTable("SomeThingAddress"); }); modelBuilder.Entity<SomeThingElse>().OwnsOne(ste => ste.Address, a => { a.ToTable("SomeThingElseAddress"); });
  • 您不能在DbSet<T>上以拥有的类型呼叫Entity<T>()

有关更多详细信息:EF Core Owned Entity Types Limitations