【问题标题】:How to configure this one-to-zero-or-one relationship?如何配置这种一对零或一的关系?
【发布时间】:2019-04-28 10:43:08
【问题描述】:

我知道有一些关于 1:0..1-relationships 的问题已回答。我查看了thisthis,但认为它们不适用于我的问题。

我在 CMS 系统中有这三个(简化的)模型。

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

FrontPageItem 与每个不同元素类型之间的关系是一对零或一。一个元素可以存在而不添加为FrontPageItem,这意味着FrontPageItem 只与一个元素有关系,要么是Article,要么是WebPage

为了配置关系,我添加了这段代码:

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

但我不认为这是正确的。我还没有为FrontPageItem 制作CRUD 视图,但是如果我尝试直接在VS 的SQL Server 对象资源管理器中添加项目,我必须为PK 输入一个值。

我做错了什么?

【问题讨论】:

  • 那么 FrontPageItem 必须有文章和网页还是只有其中之一?
  • @Nikolaus 只有其中之一。
  • 答案是否符合您的需求?
  • @Nikolaus 我还不知道。我明天看看。

标签: c# ef-code-first entity-framework-core


【解决方案1】:

如你所说:

FrontPageItem 与每个不同元素类型之间的关系是one-to-zero-or-one。元素可以存在而不添加为FrontPageItem,这意味着FrontPageItem 只与一个元素有关系,ArticleWebPage

然后从FrontPageItem中删除ArticleIdWebPageId作为EF核心支持one-to-one-or-zero在原理表中没有外键的关联:

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

然后是ArticleWebPageFleunt API配置如下:

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
}

【讨论】:

  • 你搞砸了依赖角色和主体角色——它应该与你正在做的完全相反。现在的答案是完全错误的,并导致 OP 走向错误的方向。
  • 您也可以阅读它,还有他们的follow up issue 由您的回答引起。即使只是从您提到的引用部分,很明显ArticleWebPage 是主体,而FrontPageItem 是依赖项(引用其中之一)。
  • 好的!如果确实如此,那么OP在这里错误地问了这个问题。此外阅读OP的第二个问题,他错误地描述了关系!
  • 我同意,但这就是我们在这里的原因:) 请注意,1:0..1 并没有定义谁是委托人。假设我们有AB。从AB 是 1 A 到 0..1 B。但是从 B 来看,它也是 1 B 到 0..1 正如你所看到的,它所说的只是每个实体可以单独存在 w/另一个。所以对于一对一的关系,首先要弄清楚谁是委托人,其次是需要与否的依赖关系中的FK。就这样。其他的只是几个流畅的 API 调用。
  • 是的!你是绝对正确的!他让我们对实际的关系感到困惑!谁是主,谁是依附!
猜你喜欢
  • 2016-09-20
  • 1970-01-01
  • 2014-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-25
  • 1970-01-01
相关资源
最近更新 更多