简体   繁体   English

EF Core 2.2中的不同类一对一

[英]One-to-one with different classes in EF Core 2.2

I'd like to follow this blog explaining how to configure one-to-one relationship. 我想关注这个博客,解释如何配置一对一关系。 Its idea is that one entity gets a property of the other's type while the other one gets a property of the former's type plus an ID to it to create a foreign key. 它的想法是,一个实体获得另一个类型的属性,而另一个获得前者类型的属性以及为其创建外键的ID。

My issue is, though, that I want to brake out the contact part of two different classes like so. 但我的问题是,我想像这样制动两个不同类的接触部分。 The class SomeThing is already refactored and works well with the class Address . SomeThing类已经被重构,并且可以与Address一起很好地工作。 However, I'm not sure how to deal with the class SomeThingElse . 但是,我不确定如何处理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; }
}

I've tried adding a specialized class for managing the address of SomeThingElse but then, it makes no sense to break it out. 我尝试添加一个专门的类来管理SomeThingElse的地址,但是将其分解是没有任何意义的。 I considered adding the two fields below but rejected the idea as poor design for the DB. 我考虑过在下面添加两个字段,但由于数据库设计不良而拒绝了这个想法。

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

Preferably, this is a school book case for inheritance introducing a base class Contactable and skipping Address altogether. 优选地,这是用于继承的教科书箱,其引入了基类Contactable并且完全跳过了Address But I recall from before that inheritance and EF don't mix well and that there's a lot of oopsies and gotchas to be expected in such case. 但是我记得从前,继承和EF混合得不好,并且在这种情况下会有很多麻烦和麻烦。

Is there a reliable best-practice for doing that? 有可靠的最佳做法吗? I haven't found anything that felt trustable enough when I googled. 当我用Google搜索时,没有发现任何可以信赖的东西。

As from the discussion in the comments, I am going into a details answer: 从评论中的讨论中,我将进入一个详细的答案:

You can use EF Core newly introduced Owned Entity type feature where Address is the Owned Entity type of Something and SomethingElse while Something and SomethingElse are the owners as follows: 您可以使用EF Core新引入的拥有实体类型功能,其中AddressSomethingSomethingElseOwned Entity类型,而SomethingSomethingElse是拥有者,如下所示:

modelBuilder.Entity<SomeThing>().OwnsOne(st => st.Address);
modelBuilder.Entity<SomeThingElse>().OwnsOne(st => st.Address);

By convention, EF Core will name the database columns for the properties of the owned entity type following the pattern Navigation_OwnedEntityProperty . 按照约定,EF Core将按照Navigation_OwnedEntityProperty模式为拥有实体类型的属性命名数据库列。 Therefore the Address properties will appear in the Something and SomethingElse table with the names 'Address_Street' and 'Address_City'. 因此,“ Address属性将显示在SomethingSomethingElse表中,名称为“ Address_Street”和“ Address_City”。

Now if you don't want owned entity type column name to be like Navigation_OwnedEntityProperty then you can give your custom column name as follows: 现在,如果您不希望拥有实体类型的列名像Navigation_OwnedEntityProperty那样,则可以按如下所示提供自定义列名:

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

Moreover owned types can be stored in a separate table from the owner. 此外,可以将拥有的类型与所有者存储在单独的表中。 In order to override the convention that maps an owned type to the same table as the owner, you can simply call ToTable and provide a different table name as follows: 为了覆盖将拥有的类型映射到与所有者相同的表的约定,您可以简单地调用ToTable并提供一个不同的表名,如下所示:

modelBuilder.Entity<SomeThing>().OwnsOne(st => st.Address,
      a =>
      {
            a.ToTable("SomeThingAddress");
      });

 modelBuilder.Entity<SomeThingElse>().OwnsOne(ste => ste.Address,
      a =>
      {
          a.ToTable("SomeThingElseAddress");
      });

Querying owned types 查询拥有的类型

When querying the owner the owned types will be included by default. 查询所有者时,默认情况下将包括拥有的类型。 It is not necessary to use the Include method, even if the owned types are stored in a separate table. 即使拥有的类型存储在单独的表中,也不必使用Include方法。

Limitations 限制

Some of these limitations are fundamental to how owned entity types work, but some others are restrictions that we may be able to remove in future releases: 这些限制中的一些是所有权实体类型如何工作的基础,但是其他一些限制是我们可以在将来的版本中删除的限制:

By-design restrictions: 设计限制:

  • You cannot create a DbSet<T> for an owned type 您不能为拥有的类型创建DbSet<T>
  • You cannot call Entity<T>() with an owned type on ModelBuilder 您不能在ModelBuilder上使用拥有类型调用Entity<T>()

For more details: EF Core Owned Entity Types Limitations 有关更多详细信息: EF核心拥有的实体类型限制

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM