繁体   English   中英

没有链接表/模型的多对多关系?

[英]Many-to-many relationships without link tables/models?

我正在创建一个 ASP.NET Web API 项目(首先是数据库),它从 MSSQL 数据库中提取数据(只读访问)。 数据库有几个表,但没有主/副键(我们不能改变它)。 我已经建立了一对多的关系,没有任何问题,但是当涉及到多对多时,我不得不使用链接表来保存双方的密钥。

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

链接表:

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

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

因为数据库中不存在链接表,所以我收到“Data.SqlClient.SqlException: 'Invalid object name 'StudentCourse'”错误。

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

我考虑过在这些键上连接表,但它似乎不是处理关系和获取相关记录的有效方法。 你会建议什么解决方法?

实体框架是一个对象到关系的映射器,映射器是这里的关键术语。 为了在要映射的对象之间建立关系,关系数据库中的这些实体之间必须存在关系。

这样想一下,如果学生和课程之间存在关系,那么这种关系在您的数据库中是如何表示的? 如果我让您针对该数据库编写两个 SQL 查询,您将如何返回以下数据?

  • 列出特定课程的所有学生。
  • 列出特定学生的所有课程。

你不能只用一个课程和一个学生表来做到这一点。 如果没有链接表,那么您要么以一种方式或另一种方式拥有一对多关系,要么数据库以非关系方式处理它。 (例如 Student 包含一个带有逗号分隔的课程 ID 列表的字符串字段)在这种情况下,EF 将无济于事。

如果数据库不支持记录学生和他们的课程之间的映射,您可以在其中查询一个学生如何参加多门课程,而每门课程可以有多名学生参加,那么 EF 无法配置为以某种方式自动神奇地读取和持久化此类一种关系。 数据库中必须存在多对多表,否则这种关系不存在。 使用 EF6 和 EF Core 5+,您可能会读到 EF 可以在没有链接实体的情况下处理多对多关系,这是真的,但这并不意味着没有链接 该表必须存在,但您不需要定义 StudentCourse(或 CourseStudent)实体。

代替:

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

在学生和课程中,学生可以拥有:

public IList<Course> Courses { get; set; }

而课程有:

public IList<Student> Students { get; set; }

这仍然通过链接表进行映射,并且如果该关系仅由表中的 StudentId 和 CourseId 组成,没有其他需要映射/配置的列,EF 可以完全在幕后管理该关系和表。

如果有一个链接表,只是没有按照您的期望命名:您可以随意调用实体,并通过属性、 DbContext.OnModelCreating(ModelBuilder)EntityTypeConfiguration使用配置将该实体和属性映射到现有表和列,但它们可能会被命名。 但是必须存在这样一个表来支持这种关系。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM