【问题标题】:One to many relationship: why does ID field go in other entity?一对多关系:为什么 ID 字段会进入其他实体?
【发布时间】:2015-08-29 21:47:21
【问题描述】:

在实体框架中,当我想指定一个实体具有许多其他类型的实体时,它似乎对我做事。

例如,假设我有一个关键字实体,它在我的应用程序中的多个地方使用。所有关键字都是唯一的,但在我的其他实体上,我希望附加多个关键字,所以对我来说这是有道理的:

class Page
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Keyword> Keywords { get; set; }
}

class Search
{
    public int ID { get; set; }
    public DateTime Date { get; set; }

    public virtual ICollection<Keyword> Keywords { get; set; }
}

class Keyword
{
    public int ID { get; set; }
    public string Name { get; set; }
}

但是,当我这样做时,外键被添加到 Keyword 表中,而我希望它位于实际实体上,因此我可以在数据库中查看它并查看关键字的小列表,而不是查看关键字并查看大量可笑的页面结果。

所以改为让实体框架将Keyword_IDs 放在PageSearch 实体上,我正在这样做:

class Page
{
    public int ID { get; set; }
    public string Name { get; set; }
}

class Search
{
    public int ID { get; set; }
    public DateTime Date { get; set; }
}

class Keyword
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Page> Pages { get; set; }
    public virtual ICollection<Search> Searches { get; set; }
}

这感觉倒退了,因为我在实体上指定了没有在数据库表中获取外部 ID 字段的关系。

我觉得我做错了什么,因为我应该能够通过查看我的搜索和页面类来查看关系。

对于这个基本问题,我很抱歉,但由于某种原因,我已经阅读了文档,但我并没有完全理解它。

【问题讨论】:

  • 在你的第一个例子中,你最终得到了什么数据库模式?你希望它看起来像什么?在查询分析器中,您现在返回了哪些行?您希望如何返回行?
  • 第一个示例我在关键字表中获得 Search_ID 和 Page_ID 列,而在搜索或页表中没有任何 Keyword_ID。第二个示例我在搜索和页表中获得 Keyword_ID(这是我更喜欢的)。对我来说,这似乎又回到了前面
  • 您的第二个示例意味着您只能有一个关键字用于搜索(或页面)。我想你想要的是 many-to-many 关系。

标签: entity-framework


【解决方案1】:

在一对多关联中,始终是 many 方引用 one 方。你还会如何实现它?如果Page 有一个KeywordId 作为FK,那么它永远只能有一个关键字。

此外,即使一个关键字属于无数页面,这并不意味着您总是必须通过一个关键字访问所有这些页面。只有在搜索使用特定关键字的页面时,您才会这样做。

但现在回到你的模型。你不能在这里有一对多的关联。这意味着任何关键字只能属于一个Page 或一个Search。如果按照您的建议颠倒关系,PageSearch 只能有一个关键字(Keyword_ID 所指的关键字)。

实际上,您正在处理多对多关联,好消息是,它使您的 Keyword 保持不变。

将其建模为多对多不会改变模型的外观(第一个版本),但映射不同:

modelBuilder.Entity<Page>().HasMany(p => p.Keywords)
    .WithMany()
    .Map(m =>
        {
            m.ToTable("PageKeyword");
            m.MapLeftKey("PageID");
            m.MapRightKey("KeywordID");
        });

modelBuilder.Entity<Search>().HasMany(s => s.Keywords)
    .WithMany()
    .Map(m =>
        {
            m.ToTable("SearchKeyword");
            m.MapLeftKey("SearchID");
            m.MapRightKey("KeywordID");
        });

这将在您的数据库中生成两个联结表PageKeywordSearchKeyword 记录多对多关联。

【讨论】:

    猜你喜欢
    • 2018-06-07
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多