Core 中的模型继承和数据库规范化
Model Inheritance and DB Normalization in Core
使用 C# ASP.NET Core 2.1 MVC 并遵循 Contoso 教程,其中您有一个学生模型和一个从具有公共属性的人员模型继承的教师模型。迁移后,这会生成一个带有 "Discriminator" 字段的人员 table。
当需要 3NF 规范化时,这个 table 是否带有 Discriminator acceptable,或者是否有一种方法可以减少冗余代码,同时为数据库管理员生成规范化布局?
编辑回复评论:
这就是我喜欢堆栈溢出的地方,分享想法和解释。所以这是我对 3NF 的解释,如果我错了,请分享你的解释,以便我学习。
public abstract class BaseModel
{
public int ID { get; set; }
}
public abstract class Person : BaseModel
{
public string LastName { get; set; }
public string FirstName { get; set; }
}
public class Student : Person
{
public DateTime EnrollmentDate { get; set; }
}
public class Instructor : Person
{
public DateTime HireDate { get; set; }
}
结果是单个 "People" table:
编号 |姓 |名字 |判别器 |雇用日期 |入学日期
Discriminator 是 NVARCHAR(MAX) 或换句话说,一个字符串将是 "Instructor" 或 "Student"
鉴别器因此将具有冗余值,这些值应该在它们自己的 table 中并使用整数外键。
还存在传递依赖关系,因为 Student 确定 EnrollmentDate 但与 HireDate 无关,而 Instructor 则相反。因此,任何一个日期列都不属于此 table,我相信此 table 甚至不符合 2NF 的要求。
我相信一组正确规范化的 table 应该是这样的:
-人物-
编号 |姓 |名字
-同学们-
人号 |入学日期
-导师-
人号 |雇用日期
或
-同学们-
编号 |姓 |名字 |入学日期
-导师-
编号 |姓 |名字 |雇用日期
所以回到最初的 post 和问题,是一个 "master" table 带有鉴别器列是否可以规范化,因为目标应该被正确地构造 tables 用于数据库管理员,同时删除冗余属性,让程序员担心编写格式、验证和错误消息。关于第二点,请分享其他解决方案,例如是否可以在 DTO 或 ViewModel 中进行数据验证。
修复是删除单行
型号:
public abstract class BaseModel
{
public int ID { get; set; }
}
public abstract class BasePerson
{
public string LastName { get; set; }
public string FirstName { get; set; }
}
public class Student
{
public DateTime EnrollmentDate
}
public class Instructor
{
public DateTime HireDate
}
数据库上下文:
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options)
: base(options)
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Instructor> Instructors { get; set; }
// public DbSet<BasePerson> People { get; set; }
}
如果像 Contoso 教程中那样包含 People DbSet,当您执行迁移和更新数据库时,您会在数据库中得到一个 People table,在所有继承的字段之后有一个名为 Discriminator 的列它将具有 Student 或 Instructor 的值以及 table.
末尾的任何唯一字段
我突然想到,BaseModel 中没有一个模型 table,因为 DbContext 中没有 DbSet< BaseModel > 模型。所以我尝试了它并且它起作用了,删除了 DbSet< BasePerson > People 的行,你得到的是单独的 tables for Students and Instructors with all inherited fields.
使用 C# ASP.NET Core 2.1 MVC 并遵循 Contoso 教程,其中您有一个学生模型和一个从具有公共属性的人员模型继承的教师模型。迁移后,这会生成一个带有 "Discriminator" 字段的人员 table。
当需要 3NF 规范化时,这个 table 是否带有 Discriminator acceptable,或者是否有一种方法可以减少冗余代码,同时为数据库管理员生成规范化布局?
编辑回复评论:
这就是我喜欢堆栈溢出的地方,分享想法和解释。所以这是我对 3NF 的解释,如果我错了,请分享你的解释,以便我学习。
public abstract class BaseModel
{
public int ID { get; set; }
}
public abstract class Person : BaseModel
{
public string LastName { get; set; }
public string FirstName { get; set; }
}
public class Student : Person
{
public DateTime EnrollmentDate { get; set; }
}
public class Instructor : Person
{
public DateTime HireDate { get; set; }
}
结果是单个 "People" table: 编号 |姓 |名字 |判别器 |雇用日期 |入学日期
Discriminator 是 NVARCHAR(MAX) 或换句话说,一个字符串将是 "Instructor" 或 "Student"
鉴别器因此将具有冗余值,这些值应该在它们自己的 table 中并使用整数外键。
还存在传递依赖关系,因为 Student 确定 EnrollmentDate 但与 HireDate 无关,而 Instructor 则相反。因此,任何一个日期列都不属于此 table,我相信此 table 甚至不符合 2NF 的要求。
我相信一组正确规范化的 table 应该是这样的:
-人物- 编号 |姓 |名字
-同学们- 人号 |入学日期
-导师- 人号 |雇用日期
或
-同学们- 编号 |姓 |名字 |入学日期
-导师- 编号 |姓 |名字 |雇用日期
所以回到最初的 post 和问题,是一个 "master" table 带有鉴别器列是否可以规范化,因为目标应该被正确地构造 tables 用于数据库管理员,同时删除冗余属性,让程序员担心编写格式、验证和错误消息。关于第二点,请分享其他解决方案,例如是否可以在 DTO 或 ViewModel 中进行数据验证。
修复是删除单行
型号:
public abstract class BaseModel
{
public int ID { get; set; }
}
public abstract class BasePerson
{
public string LastName { get; set; }
public string FirstName { get; set; }
}
public class Student
{
public DateTime EnrollmentDate
}
public class Instructor
{
public DateTime HireDate
}
数据库上下文:
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options)
: base(options)
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Instructor> Instructors { get; set; }
// public DbSet<BasePerson> People { get; set; }
}
如果像 Contoso 教程中那样包含 People DbSet,当您执行迁移和更新数据库时,您会在数据库中得到一个 People table,在所有继承的字段之后有一个名为 Discriminator 的列它将具有 Student 或 Instructor 的值以及 table.
末尾的任何唯一字段我突然想到,BaseModel 中没有一个模型 table,因为 DbContext 中没有 DbSet< BaseModel > 模型。所以我尝试了它并且它起作用了,删除了 DbSet< BasePerson > People 的行,你得到的是单独的 tables for Students and Instructors with all inherited fields.