【问题标题】:What type of relationship is this and how to implement it in .NET Core (EFCore, FluentAPI)?这是什么类型的关系以及如何在 .NET Core(EFCore、FluentAPI)中实现它?
【发布时间】:2020-05-19 14:36:05
【问题描述】:

我遇到的问题很简单,但我的思维停止了工作。对不起,如果我的问题很愚蠢,但我对数据库不太擅长(我也不擅长 EFCore)。

我想要以下表格:

简历:带有 ID 和姓名/职务(字符串)

技能:带有 ID 和姓名/职务(字符串)

SkillsCV:带 ID、CvID(CV 中记录的外键)、SkillID(Skills 中记录的外键)

我不想在 CVs 和 Skills 表中有 SkillsCV 的外键。是否可以? .NET Core 是否有可能,更重要的是 Fluent API? 我对 FluentAPI 做了一个小研究,两端都有外键,是一对一的关系。需要这个吗?顺便说一句,这是一对一的关系,对吧?我不想让一方知道另一方。这就是所谓的 0 到 1,还是完全不同的东西?我真的很困惑。

所以我在 FluentAPI 中看到的一对一关系,我需要以下代码:

modelBuilder.Entity<Skill>()
        .HasOne(skill => skill.SkillCV) // but I don't have a SkillCV object in Skill model
        .WithOne(skillCV => skillCV.Skill) // I have skillCV.Skill
        .HasForeignKey<SkillCV>(skillCV => skillCV.SkillID); // I have this foreign key in skillCV as well

但我不想在 Skills 表中有一个对象(或外键)(因为我不希望在 CVs 表中有这样的对象)。 这可能吗?我肯定做错了什么。 你能帮我找出我的错误(如果有的话)吗?

如果您知道更好的方法,请分享。提前致谢!

编辑:我想要创建的快速示例:

简历表:

ID、姓名

1“CV1”

2“CV2”

3“CV3”

技能表:

ID、姓名

1“C#”

2“Java”

3“蟒蛇”

SkillsCV 表:

ID、CvID、SkillID

1 1 1

2 1 3

3 2 1

这是解决这个问题的好方法吗?我还没有创建 SkillsCVs 表,现在我只有 CVs 和 Skills(每个技能都有一个 CV_ID),但是当我需要在前端填充一个选择框时,我需要从 API 返回 DISTINCT Skills(因为有 800 个 C# 例如不同 CV 的记录)。我认为 SkillsCVs 表可以解决这个问题,但我现在不完全确定:D

【问题讨论】:

  • 据我了解,您不想在两个表中的任何一个中使用该列,所以我能想到的唯一解决方案是第三个表,其中您将 cv id 与技能 id 链接.这是唯一的方法,这是您需要的吗?
  • @Diego658 我想要 3 张表(在我的问题的顶部):CVs、Skills、SkillsCV。所以,我有第三张表,其中有其他表的 2 个外键。我想在 SkillsCV 中引用 Skills 表,而在 Skills 中没有 SkillsCV 引用。一个非常快速的例子: Skills 表有以下记录: 1 C#; 2爪哇; 3 Python,在 CV 中我们有 1 CV1、2 CV2、3 CV3 - 然后我想要具有以下记录的 SkillsCV:1 CV1 1(即 C#); 2 CV1 3(即 Python); 3 CV2 1(即C#)等......
  • 为什么说是一对一的关系呢?它似乎是 CVs 和 Skills 之间的 M 对 N 关系,SkillCVs 是它的中间表。
  • 我现在得到你的模型。因此,许多 CVSkill 对应一份 CV,一份 CVSkill 对应一项技能。但在您的示例中,您在两个不同的 CV 中显示 Skill id 1...
  • 然后只需要一个多对多模型。您可以使用关联表为每个案例添加所需的附加信息。

标签: c# database entity-framework .net-core entity-framework-core-3.1


【解决方案1】:

您拥有的是many-to-many 关系。你可以这样建模:

public class Skill
 {
    public int Id { get; set; }

    public string Name { get; set; }
 }

 public class CV
 {
    public int Id { get; set; }

    public string Name { get; set; }
 }

 public class SkillCV
 {
    public int SkillID { get; set; }

    public Skill Skill { get; set; }

    public int CVID { get; set; }

    public CV CV { get; set; }
 }

然后要使用 Fluent API 进行设置,您可以这样做:

modelBuilder.Entity<SkillCV>()
    .HasKey(t => new { t.SkillID, t.CVID});

modelBuilder.Entity<SkillCV>()
    .HasOne(pt => pt.Skill)
    .WithMany()
    .HasForeignKey(pt => pt.SkillID);

modelBuilder.Entity<SkillCV>()
    .HasOne(pt => pt.CV)
    .WithMany()
    .HasForeignKey(pt => pt.CVID);

这样你以后的连接会很简单,SkillCV 表将有一个由SkillIDCVID 组成的复合键(确保参照完整性)。

【讨论】:

  • 是的,我想通了。多次使用多对多,但今天我真的很困惑,因为我从一对多开始,我的头脑开始集思广益,我真的很困惑。感谢您提供的好示例 + Fluent API 代码。我真的很感激!
【解决方案2】:

如果我理解正确,您只能使用注释。

 public class Skill
 {
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
 }
 public class Cv
 {
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
 }
 public class SkillCv
 {
    [ForeignKey("Skill")]
    public int SkillId { get; set; }
    [ForeignKey("Cv")]
    public int CvId { get; set; }

    public virtual Skill Skill{ get; set; }

    public virtual  Cv Cv { get; set; }
 }

public class TestContext : DbContext
{
    public DbSet<Skill> Skills { get; set; }
    public DbSet<Cv> Cvs { get; set; }
    public DbSet<SkillCv> SkillCvs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //The entity does not have its own key, only the relationship of the two
        modelBuilder.Entity<SkillCv>().HasNoKey();
    }

}

因此,您将在表格中为每个具有 cv 的技能提供一行

var allSkillFromCv = await _context.SkillCvs.Where(s => s.CvId == 1).ToListAsync()

如果你想使用导航属性

var allSkillFromCv = await _context.SkillCvs.Where(s => s.CvId == 1).Include(s => s.Skill).ToListAsync();

【讨论】:

  • 我认为多对多是解决方案。我在问题下方的 cmets 的帮助下弄清楚了。但我很欣赏你给出的详细例子。谢谢你。这是无钥匙实体模型的示例吗?我过去做过类似的事情,但有一个脚本迁移。
  • 是的,它是一个无键实体,但您应该考虑为列添加索引,因为当您有数千行时,它们会极大地帮助您提高查询速度。 SkillCv 实体只是多对多关系。
【解决方案3】:

这里需要三个表:CVs 表、Skills 表和 SkillsCVs 表。你有一个 简历表和技能表之间的多对多关系。您必须使用 Fluent API 定义多对多关系。你需要在简历表和技能表中都有导航属性

public class CV
{
    .... 

    public IList<SkillCV> SkillsCVs { get; set; }
}
 public class Skill
 {
        .... 

        public IList<SkillCV> SkillsCVs { get; set; }
 }

在数据库上下文中

  public DbSet<SkillCV> SkillsCVs { get; set; }

您还需要使用 Fluent API 定义关系

modelBuilder.Entity<SkillCV>()
    .HasOne<Skill>(sc => sc.Skill)
    .WithMany(s => s.SkillsCVs)
    .HasForeignKey(sc => sc.SkillID);


modelBuilder.Entity<SkillCV>()
    .HasOne<CV>(sc => sc.CV)
    .WithMany(s => s.SkillsCVs)
    .HasForeignKey(sc => sc.CvID);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-12
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    相关资源
    最近更新 更多