您提到您在个人资料和关注者之间存在一对多的关系。
通常这意味着每个个人资料都有零个或多个追随者,并且每个追随者都属于一个个人资料。换句话说:追随者有个人资料,而不是是个人资料。在软件设计方面:Follower 使用 Composition 来描述其与 Profile 的关系。它不使用继承。
这样做的原因是,如果您有一个配置文件 P1,其中有两个追随者 F1 和 F2,则两个追随者都有指向同一个 P1 的东西。
效果是,当改变follower F1的Profile的任何一个属性时,follower F2的Profile中的这些属性也会改变。这是预期行为,因为 F1 的配置文件与 F2 的配置文件相同。
如果您使用继承来为追随者的个人资料部分建模,那么 F1 和 F2 都将拥有自己的个人资料。更改 F1 的配置文件属性不会更改 F2 的配置文件属性。
如果你真的想要后者,你的设计不是一对多的
关系。稍后看如何实现继承
Proper configuration of one-to-many relation:
class Profile
{
public int Id {get; set;}
// a Profile has zero or more followers:
public virtual ICollection<Follower> Followers {get; set;}
...
}
class Follower
{
public int Id {get; set;}
// a follower belongs to exactly one Profile (via foreign key ProfileId)
public int ProfileId {get; set;}
public virtual Profile Profile {get; set;}
...
}
优点是实体框架会自动将其识别为一对多关系。不需要属性,也不需要流畅的 API。此外:其他开发人员会立即看到您打算设计一对多关系。
实体框架中的继承
如果您打算实现继承,有几种策略可以做到这一点。我最常用的是Table-Per-Concrete-Class (TPC).
在 TPC 中,每个将具有实例化对象的类都有自己的表。该表具有类的属性以及基类的属性。
这种设计最容易被别人理解,并且提供了最简单的数据库,可以快速检索和更新。对于您要访问的每个对象,只需要一个表。
除此之外,这完全模仿了继承的软件行为:如果您创建了一个 Follower 对象,该对象将自动具有 Profile 属性。如果您删除 Follower 对象,它的 Profile 属性也会被删除。更改追随者的个人资料属性之一,不会影响任何其他追随者的个人资料属性。
class Profile
{
... // profile properties
}
// A Follower IS a Profile:
class Follower : Profile
{
public int Id {get; set;}
... // Follower properties
}
class MyDbContrext : DbContext
{
public DbSet<Follower> Followers{get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// tell that the Profile base class properties of Follower should be in the
// Followers table:
modelBuilder.Entity<Follower>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable(nameof(MyDbContext.Followers));
});
}