如何处理同一实体类型的多个一对零或一对一关系?

How to handle multiple one-to-zero-or-one relationships of the same entity type?

据我了解,EF6 通过在相关实体上共享相同的 ID 来实现一对零或一关系,并将其投射到数据库中

tutorial 说:

A one-to-zero-or-one relationship happens when a primary key of one table becomes PK & FK in another table in a relational database such as SQL Server. So, we need to configure the above entities in such a way that EF creates the Students and StudentAddresses tables in the DB and makes the StudentId column in Student table as PrimaryKey (PK) and StudentAddressId column in the StudentAddresses table as PK and ForeignKey (FK) both.

所以如果 Website 有一个可选的 WebsitePage,我可能有这个:

public class Website
{
    public int Id { get; set; }
    public virtual WebsitePage Page { get; set; }
}


public class WebsitePage
{
    [Key, ForeignKey( nameof( Website ) )]
    public int Id { get; set; } 
    public virtual Website Website { get; set; }
}

但是如果我想要多个可选页面怎么办,就像这样?

public class Website
{
    public int Id { get; set; }
    public virtual WebsitePage AboutPage { get; set; }
    public virtual WebsitePage ServicesPage { get; set; }
    public virtual WebsitePage CaseStudyPage { get; set; }
}


public class WebsitePage
{
    [Key, ForeignKey( nameof( Website ) )]
    public int Id { get; set; } 
    public virtual Website Website { get; set; }
}

可能是我今天的谷歌搜索不合格,但我无法在网上或此处找到任何此类示例。

是我遗漏了什么,还是我的理解有问题?

最初我误解了你要实现的关系的标题。 One-to-zero-or-one 当我们对一个模型在另一个模型中有多个引用时,无法建立关系。你要的是one-to-many关系;一方面我们有 1 WebsitePage object,另一方面,我们有 n 相关的 Website object 可以有 1-3 WebsitePages(请参阅评论)。为此,您可以使用 可空外键 。 在导航属性旁边提供可为 null 的 ID 属性:

public class Website
{
  [Key]
  public int Id { get; set; }

  public int? AboutPageId { get; set; }
  public virtual WebsitePage AboutPage { get; set; }

  public int? ServicesPageId { get; set; }
  public virtual WebsitePage ServicesPage { get; set; }

  public int? CaseStudyPageId { get; set; }
  public virtual WebsitePage CaseStudyPage { get; set; }
}


public class WebsitePage
{
  [Key]
  public int Id { get; set; }
}

WebsiteId in WebsitePage 模型不是必需的。参见 EF6 built-in conventions

您也可以使用 Fluent API,就像他们在您链接的教程中所做的那样。

编辑:如果您希望每个页面只属于一个网站,您可能需要分离模型并使用中间模型:

public class Website
{
  [Key]
  public int Id { get; set; }

  public virtual IList<WebsitePage> WebsitePages { get; set; }
}

public class Page
{
  [Key]
  public int Id { get; set; }

  //public PageType Type { get; set; }

  public virtual IList<WebsitePage> WebsitePages { get; set; }
}

public class WebsitePage
{
  [Key, ForeignKey(nameof(Page))]
  public int PageId { get; set; }
  public virtual Page Page { get; set; }

  public int WebsiteId { get; set; }
  public virtual Website Website { get; set; }
}

PageId不能重复,每条记录需要一个WebsiteId;每个页面将只属于一个网站(如果有的话)。它已通过 .NET Core 3.1/EF Core 2.2 测试。

同样,您可能只能使用两个模型(WebsitePage)和 Fluent API 来指定它们之间的 many-to-many 关系必须如何防止重复。