1

I know there are some answered questions on SO about 1:0..1-relationships. I have looked at this and this, but don't think they apply to my question.

I have these three (simplified) models in a CMS-system.

public class FrontPageItem
{
    public int Id { get; set; }
    public int ItemType { get; set; } // 1 = Article, 2 = WebPage, etc...

    public int? ArticleId { get; set; }
    public Article Article { get; set; }

    public int? WebPageId { get; set; }
    public WebPage WebPage { get; set; }
}

public class Article
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Preamble { get; set; }
    public string MainText { get; set; }

    public int? FrontPageItemId { get; set; }
    public FrontPageItem FrontPageItem { get; set; }
}

public class WebPage
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int? FrontPageItemId { get; set; }
    public FrontPageItem FrontPageItem { get; set; }
}

The relationships between a FrontPageItem and each of the different element types are one-to-zero-or-one. An element can exist without being added as a FrontPageItem, meaning that a FrontPageItem has a relationship to just one element, either an Article or a WebPage.

In an attempt to configure the relationships, I have added this bit of code:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Article>()
        .HasOne(p => p.FrontPageItem)
        .WithOne(i => i.Article)
        .HasForeignKey<FrontPageItem>(b => b.Id);
    modelBuilder.Entity<WebPage>()
        .HasOne(p => p.FrontPageItem)
        .WithOne(i => i.WebPage)
        .HasForeignKey<FrontPageItem>(b => b.Id);
}

But I don't think it's correct. I haven't made the CRUD-views for FrontPageItem yet, but if I try to add items directly in the SQL Server Object Explorer in VS, I have to enter a value for the PK.

What am I doing wrong?

ArunPratap
  • 4,816
  • 7
  • 25
  • 43
Stian
  • 1,522
  • 2
  • 22
  • 52

1 Answers1

1

As you said:

The relationships between a FrontPageItem and each of the different element types are one-to-zero-or-one. An element can exist without being added as a FrontPageItem, meaning that a FrontPageItem has a relationship to just one element, either an Article or a WebPage.

Then remove ArticleId and WebPageId from FrontPageItem as EF core support one-to-one-or-zero association without foreign key in principle table:

public class FrontPageItem
{
    public int Id { get; set; }
    public int ItemType { get; set; } // 1 = Article, 2 = WebPage, etc...

    public Article Article { get; set; }
    public WebPage WebPage { get; set; }
}

Then the Fleunt API configuration for Article and WebPage as follows:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Article>()
        .HasOne(a => a.FrontPageItem)
        .WithOne(f => f.Article)
        .HasForeignKey<Article>(a => a.FrontPageItemId); // <-- Here it is

    modelBuilder.Entity<WebPage>()
        .HasOne(wp => wp.FrontPageItem)
        .WithOne(f => f.WebPage)
        .HasForeignKey<WebPage>(wp => wp.FrontPageItemId); // <--Here it is
}
TanvirArjel
  • 30,049
  • 14
  • 78
  • 114
  • 1
    You've messed up the dependent and principal roles - it should be exactly the opposite of what you are doing. The way it is now the answer is simply wrong and leads OP in a wrong direction. – Ivan Stoev May 01 '19 at 22:02
  • You can read it too, and also their [follow up issue](https://stackoverflow.com/questions/55942221/why-arent-related-entities-loaded-on-include) caused by your answer. Even just from the quoted part you've mentioned, it's pretty obvious that `Article` and `WebPage` are principals, and `FrontPageItem` is the dependent (referencing one of them). – Ivan Stoev May 01 '19 at 23:48
  • Okay! If it really then OP asked the question wrongly here. Moreover read the OP‘s second question where he has described the relation wrongly! – TanvirArjel May 01 '19 at 23:54
  • 1
    I agree, but that's why we are here :) And note that 1:0..1 doesn't define who is the principal. Say we have `A` and `B`. Looking from `A` to `B` it's 1 A to 0..1 B. But looking from B, it's also 1 B to 0..1 As you can see, all it says is that each entity can exist separately w/o the other. So with one-to-one relationships, the first thing to be figured out is who is the principal, and second is the FK in the dependent required or not. And that's all. All other is just a few fluent API calls. – Ivan Stoev May 02 '19 at 00:11
  • Yes! You are absolutely correct! He confused us about the what actual relationship is! Who is the principle or who is the dependent! – TanvirArjel May 02 '19 at 00:14
  • @TanvirArjel I can assure you - I am confused myself. ;) – Stian May 02 '19 at 07:02