站点图标 江湖人士

Entity Framework Core使用Fluent API 配置数据库表多对多关系

EF Core获取上下文SQL语句

EF Core获取上下文SQL语句

本篇文章中,您将学习如何使用Entity Framework Core中的Fluent API配置两个实体之间的多对多关系。

让我们实现以下StudentCourse实体之间的多对多关系,其中一个学生可以注册许多课程,同样,一门课程可以由许多学生加入。

public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }
}

public class Course
{
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public string Description { get; set; }
}

数据库中的多对多关系由连接表表示,该连接表包括两个表的外键。此外,这些外键是复合主键。

约定

Entity Framework Core中没有可自动配置多对多关系的默认约定。您必须使用Fluent API对其进行配置。

Fluent API

在Entity Framework 6.x或更早版本中,EF API用于为多对多关系创建连接表。我们不需要为连接表创建连接实体(但是,我们当然可以在EF 6中明确创建连接实体)。

在Entity Framework Core中,尚未实现。我们必须为连接表创建一个连接实体类。上述StudentCourse实体的加入实体应包括每个实体的外键属性和引用导航属性。

配置多对多关系的步骤如下:

  1. 定义一个新的连接实体类,其中包括每个实体的外键属性和引用导航属性。
  2. 定义其他两个实体和实体加盟之间的一个一对多的关系,通过在实体的集合导航属性两侧(StudentCourse,在这种情况下)。
  3. 使用Fluent API将加入实体中的两个外键配置为组合键。

因此,首先,定义加入实体StudentCourse,如下所示。

public class StudentCourse
{
    public int StudentId { get; set; }
    public Student Student { get; set; }

    public int CourseId { get; set; }
    public Course Course { get; set; }
}

上述接合实体StudentCourse包括参考导航属性StudentCourse及其外键特性StudentIdCourseId分别(外键属性遵循惯例)。

现在,我们还需要在Student– > StudentCourseCourse– > StudentCourse实体之间配置两个单独的一对多关系。我们可以通过遵循一对多关系的约定来实现,如下所示。

public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }

    public IList<StudentCourse> StudentCourses { get; set; }
}

public class Course
{
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public string Description { get; set; }

    public IList<StudentCourse> StudentCourses { get; set; }
}

如您所见,实体StudentCourse实体现在包含StudentCourse类型的集合导航属性。该StudentCourse实体已包含两者的外键属性和导航属性,StudentCourse。这使它成为StudentStudentCourseCourse&之间完全定义的一对多关系StudentCourse

现在,外键必须是连接表中的复合主键。这只能使用Fluent API进行配置,如下所示。

public class SchoolContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=.\SQLEXPRESS;Database=EFCore-SchoolDB;Trusted_Connection=True");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<StudentCourse>().HasKey(sc => new { sc.StudentId, sc.CourseId });
    }
    
    public DbSet<Student> Students { get; set; }
    public DbSet<Course> Courses { get; set; }
    public DbSet<StudentCourse> StudentCourses { get; set; }
}

在上面的代码中,配置并作为复合键。modelBuilder.Entity<StudentCourse>().HasKey(sc => new { sc.StudentId, sc.CourseId })StudentIdCourseId

如果实体遵循与加入实体的一对多关系的约定,则可以配置多对多关系。假设外键属性名称不符合约定(例如SID而不是StudentId和CID而不是CourseId),那么您可以使用Fluent API对其进行配置,如下所示。

modelBuilder.Entity<StudentCourse>().HasKey(sc => new { sc.SId, sc.CId });

modelBuilder.Entity<StudentCourse>()
    .HasOne<Student>(sc => sc.Student)
    .WithMany(s => s.StudentCourses)
    .HasForeignKey(sc => sc.SId);


modelBuilder.Entity<StudentCourse>()
    .HasOne<Course>(sc => sc.Course)
    .WithMany(s => s.StudentCourses)
    .HasForeignKey(sc => sc.CId);

退出移动版