【问题标题】:Relationship with another Entity when using inheritance on parent class or on child classes在父类或子类上使用继承时与另一个实体的关系
【发布时间】:2021-05-05 09:25:52
【问题描述】:

我有以下继承。医生是父类。医生可以是儿科医生、牙医或骨科医师。每种医生类型都有不同的属性(不同的领域逻辑),但他们都共享相同的 ID、姓名,而且他们都可以有很多预约。

public abstract class Doctor
{
    public long Id { get; set; }

    public string Name { get; set; }
}

public class Paediatrician : Doctor
{
    // add some other properties specific only to Paediatrician.
}

public class Orthopaedic : Doctor
{
    // add some other properties specific only to Orthopaedic.
}

public class Dentist : Doctor
{
    // add some other properties specific only to Dentist.
} 

public class Appointment
{
    public long Id { get; set; }
    public DateTime DateOfAppointment { get; set; }
}

public class Country
{
    public long Id { get; set; }
    public string Name { get; set; }
}

这里有一对多的关系(医生可以有很多预约)。这里的问题是我在哪里添加约会关系?在每个子类内部还是在父类上?我必须将此关系设置为我的 ORM,因此将这种关系添加到每个子类中会在我的数据库中产生三种不同的关系,而如果我将它添加到父类中只有一个?同样代表国家表。我在哪里添加国家关系?仅在父类或子类上?
可能会影响我的选择的系统要求之一是我必须显示一个包含医生姓名和预约日期的列表视图。所以有两种方法可以做到这一点。如果我将约会关系添加到父类,则可以通过调用每个子类并聚合结果,或者直接调用父类并获取约会。我被卡住了,根本不知道这样做的正确方法是什么。

【问题讨论】:

  • stackoverflow 上的段落是免费的
  • 这不是一个真正的编程问题,而是一个关系数据库问题。但是,inheritance is described in the Microsoft docs。 (近年来,Microsoft 文档已经变得相当好(与过去相比)。)我认为如果有多个导数,则每个层次结构的表会变得相当大。 Table-per-type 似乎更合乎逻辑,尽管有一个额外的间接级别,性能较差(见页面底部评论)。
  • @JHBonarius 但即使在 TPT 中,在哪里添加了共同关系?在父类或子类中。 EF Core 的文档没有说明这样的场景(大多数示例通常都显示非常简单的示例),给更复杂的场景留下了很大的问号
  • 稍后我会改进我的答案。但据我所知,约会清单应该在基础上。为什么不呢?就像 id 和 name 很常见一样......为什么常见的列表会不同?
  • 如果在基类中可以直接查询基类吗?继承的目的不就是隐藏基类,只处理子类吗?

标签: c# .net inheritance entity-framework-core


【解决方案1】:

这个问题并不特定于 C# .Net 或实体框架,但通常与对象关系有关。

第一点是继承。派生类从基类继承所有公共和受保护的属性(并且可以访问具有相同限定符的方法)。 IE。 Dentist 也将有 IdName,尽管您没有在类中声明它们。它们继承自Doctor

第二点是对象关系。显然Dentist 可以生成AppointmentPaediatrician 也可以。两者都是Doctor 的类型。正如您所说,存在一对多的关系。 “许多”是Appointment,但你想要“一个”是什么?当然你可以选择Dentist或者Paediatrician。但是你必须预约一个通用类

    public class Appointment<T> where T : Doctor
    {
        [Key]
        public long Id { get; set; }
        [Required]
        public DateTime DateOfAppointment { get; set; }
        [Required]
        public T DoctorNavigation { get; set; }
    }

每个派生类都有自己的约会列表

    public class Dentist : Doctor
    {
        ...
        public List<Appointment<Dentist>> DentistAppointments { get; set; }
    }

但是,我希望只有一个Appointments 列表,其中“一个”关系是Doctor。当然,您仍然可以为每个派生类提供其自己的约会列表,但这会导致一个奇怪的Appointment 实体,它对每个派生类都有一个可选的导航属性。

从逻辑上讲,您可以将Appointments 的列表放入Doctor(基)类中。

您需要添加一个鉴别器,以便能够从 Doctor 映射回一个导数。 嗯,判别器对 TPT 不起作用...试图弄清楚如何做到这一点。

【讨论】:

  • TPH 造成了混乱。我没有使用它,因为我的域在每个子类中都包含许多其他属性。这就是我使用 TPT 的原因,尽管它可能会产生一些性能问题,但更清楚
  • @pantonis "每个子类中的许多其他属性"
  • 没有。每种类型的医生都有自己的业务逻辑(例如,骨科有 X 光片,牙医有牙齿手术等......)并且所有医生类型都是医生(满足继承的 'is a')
  • @pantonis 更新。请让我知道您还需要什么
猜你喜欢
  • 2015-09-25
  • 1970-01-01
  • 2013-08-08
  • 2020-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
相关资源
最近更新 更多