[英]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.