数据库表间多对多关系(附带额外字段)的实体类(POJO 或 POCO)表示

时间:2023-03-08 16:37:49
数据库表间多对多关系(附带额外字段)的实体类(POJO 或 POCO)表示

介绍

在之前的 Entity Framework 快速上手介绍 之中,两个实体之间只是简单的一对一关系,而在实际的应用场景中,还会出现多对多关系,同时还有可能会出现多对多关系还附带有其他字段的情况。

下面以几个例子,对表间多对多关系的类表示加以更加详细地描述。虽然两个场景举例是使用的 C# 及 Entity Framework(Model First) 框架自动生成数据库、实体类。但这种设计方法,并不只是在使用 ORM 框架时需要,事实上,它是 POCO 及简单 Java 类(POJO)的设计原则之一。

场景实例

场景一

在考虑多对多关系还附带有字段的情况之前,让我们先看一下,多对多关系但不附带额外字段的情况下,实体类代码的表示。

此处使用 Entity Framework(Model First),快速将 model diagram 转为数据库中的表及实体类。

假设的场景是学生选课,一名学生可以选多门课,一门课也可以被多个学生选择。E-R 图如下所示:

数据库表间多对多关系(附带额外字段)的实体类(POJO 或 POCO)表示

对应自动生成的数据库如下:

数据库表间多对多关系(附带额外字段)的实体类(POJO 或 POCO)表示

  • StudentSet

    数据库表间多对多关系(附带额外字段)的实体类(POJO 或 POCO)表示
  • CourseSet

    数据库表间多对多关系(附带额外字段)的实体类(POJO 或 POCO)表示
  • CourseRegistrationSet

    数据库表间多对多关系(附带额外字段)的实体类(POJO 或 POCO)表示
    • 其中 Course_Id 与 Students_Id(注:此处词尾(s)负数的原因参见上面 E-R 图中右边的 Properties 中 End1 Navigation Property 的设置)分别以另外两张数据表的 Id 主键作为外键。
    • 同时 Course_Id与 Students_Id 两者联合做 CourseRegistrationSet 表的主键。

对应自动生成实体类的代码如下:

  • Student.cs
namespace Model
{
using System;
using System.Collections.Generic; public partial class Student
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Student()
{
this.Course = new HashSet<Course>();
} public int Id { get; set; }
public string 学号 { get; set; }
public string 姓名 { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Course> Course { get; set; }
}
}
  • Course.cs
namespace Model
{
using System;
using System.Collections.Generic; public partial class Course
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Course()
{
this.Students = new HashSet<Student>();
} public int Id { get; set; }
public string 课程名称 { get; set; }
public string 学分 { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Student> Students { get; set; }
}
}

分析

  • 数据库表之间一对一、一对多的关系在代码中是通过 对象引用对象数组/List等形式的引用 实现的。
  • 从实例中可以看出,CourseRegistrationSet 表中的多对多关系在代码中的表现形式同样是实体类中的 对象List等形式的引用,只不过多对多关系是多个实体类中都存在其他实体类对象List的引用

场景二

现在让我们增加一个需求,实际应用之中,数据库不可能仅仅存储某学生选了某门课程这些信息,同时还需要保存选课时间、操作人、成绩等等信息。

现在让我们为 CourseRegistrationSet 表增加一个字段——成绩。

  • CourseRegistrationSet

    数据库表间多对多关系(附带额外字段)的实体类(POJO 或 POCO)表示

同时我们需要更新一下程序中的代码,这时候问题出现了