【问题标题】:Give a foreign key a custom name through OnModelCreating通过 OnModelCreating 给外键一个自定义名称
【发布时间】:2021-09-20 12:06:07
【问题描述】:

如何阻止 EF Core 创建这样的名称?我有一张包含学生和锻炼的表格,我让他们为 EF Core 设置了链接表。我正在使用 EF Core 5.09。我正在关注本书的示例

https://www.learnentityframeworkcore.com/configuration/one-to-many-relationship-configuration

但我认为如果它创建了这样的名称会出现问题

public class StudentClasses
{
    public int StudentId { get; set; }
    public Students Students { get; set; }
    public int ClassId { get; set; }
    public Classes Classes { get; set; }
}

然后在OnModelCreating 覆盖中,我有以下内容:

modelBuilder.Entity<StudentClasses>()
            .HasKey(bc => new { bc.StudentId, bc.ClassId });

modelBuilder.Entity<StudentClasses>()
            .HasOne(bc => bc.Students)
            .WithMany(b => b.StudentClasses)
            .HasForeignKey(bc => bc.StudentId);

 modelBuilder.Entity<StudentClasses>()
             .HasOne(bc => bc.Classes)
             .WithMany(c => c.StudentClasses)
             .HasForeignKey(bc => bc.ClassId);

但这会导致数据库中的命名约定很糟糕。

如何让它只显示ClassId 作为外键的名称我修复了代码中的拼写错误,但我不知道如何停止它之前的类。这是一个学生可以属于多个班级的关系。

我的学生班级

public class Students
{  
    [Key]
    public int StudentId { get; set; }
    public int? Type { get; set; }
    public string? FirstName { get; set; }
    public string? Surname { get; set; }
    public DateTime? DOB { get; set; }
    public decimal? Weight { get; set; }
    public decimal? Height { get; set; }
    public int? Gender { get; set; }
    public string? Age { get; set; }

    public ICollection<StudentWorkouts> StudentWorkouts { get; set; }
    public ICollection<StudentClasses> StudentClasses { get; set; }
    public bool? IsDeleted { get; set; }
    public bool? IsActive { get; set; }
    public string? CreatedBy { get; set; }
    public string? LastModifiedBy { get; set; }
    public DateTime? LastUpdatedDate { get; set; }
    public DateTime? CreatedDate { get; set; }
}

我的Classes 班级 - 没有双关语:

public class Classes
{
    [Key]
    public int ClassedId { get; set; }
    public Guid? UserId { get; set; }
    public ICollection<Students> Students { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public ICollection<StudentClasses> StudentClasses { get; set; }
    public bool? IsDeleted { get; set; }
    public bool? IsActive { get; set; }
    public string? CreatedBy { get; set; }
    public string? LastModifiedBy { get; set; }
    public DateTime? LastUpdatedDate { get; set; }
    public DateTime? CreatedDate { get; set; }
}

【问题讨论】:

标签: c# entity-framework-core


【解决方案1】:

看起来让你搞砸的一点是:

public ICollection<Students> Students { get; set; }

EF 将在此处尝试建立的关系是学生指向班级的关键。因此,ClassesClassId 派生自 Classes 实体中的 ClassId。

如果你想让学生参加一个班级,你不应该在 Classes.StudentClasses 和 Classes.Students 之间加倍。

您的示例似乎是教科书的多对多关系。

如果您使用的是 EF Core 5,那么您现在可以避免完全声明 StudentClass 实体:

public class Student
{
    // ...
    public virtual ICollection<Classes> Classes { get; set; } = new List<Classes>();
    // ...
}

public class Classes
{
    // ...
    public virtual ICollection<Student> Students { get; set; } = new List<Students>();
    // ...
}

EF 将自动生成连接表,或者您可以映射显式连接表/实体。

EF Core 2/3.1 需要声明和直接引用连接实体,就像您下面的示例一样。这不是多对多关系,而是一对多对一关系。

如果您使用的是 EF Core 5,请提供最新参考:https://www.thereformedprogrammer.net/updating-many-to-many-relationships-in-ef-core-5-and-above/

仅当您想要访问连接实体上的非键属性时,通常才需要显式映射和使用连接实体。例如,如果您具有特定于要访问的 StudentClass 实体的属性或关系,或者在处理学生和/或班级时需要填充。如果表只是一个 StudentId 和 ClassId,那么通常最好通过Student.Classes 而不是Student.StudentClasses.Select(sc =&gt; sc.Class).ToList() 处理学生的课程集合。

如果您使用的是 EF Core 2 或 3.1,那么您基本上会被加入实体的一对多对一关系所困扰。我强烈建议推动更新到 EF Core 5,因为恕我直言,EF Core 3.1 仍然是 EF6 未实现功能的狗早餐。 :)

【讨论】:

  • 我是否不再需要我的onmodel创建以及然后
  • 你说它不需要表格但是那篇文章仍然显示 BookTags 的创建它不再需要在 dbcontext 级别。
  • 它不一定需要引用连接“实体”,它仍然在后台创建连接表。我需要用 EF Core 5 刷新我的记忆,以确定实体是否仍需要为映射声明,或者您是否可以只映射表定义(表名、列名)或让它完全管理表后面与 EF6 一起使用的场景。在任何一种情况下,您都不需要声明 StudentClasses 的 DbSet,即使您声明了 StudentClasses 实体类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-14
  • 2020-06-20
  • 2017-11-05
  • 1970-01-01
  • 2013-08-01
  • 1970-01-01
相关资源
最近更新 更多