.net 如何在数据库中有效地建模继承?

.net 如何在数据库中有效地建模继承?,.net,sql-server,oop,inheritance,database-design,.net,Sql Server,Oop,Inheritance,Database Design,数据库继承建模的最佳实践是什么 权衡是什么(例如可查询性) (我最感兴趣的是SQL Server和.NET,但我也想了解其他平台是如何解决这个问题的。)您将规范化数据库,这实际上会反映您的继承。 它可能会降低舞蹈的性能,但正常化就是这样。您可能需要使用良好的常识来找到平衡。在数据库中可以设置两种主要的继承类型,即每个实体的表和每个层次的表 每个实体的表是一个具有所有子类共享属性的基本实体表。然后,每个子类都有另一个表,每个表仅具有适用于该类的属性。他们的PK以1:1的比例联系在一起 每个层次结

数据库继承建模的最佳实践是什么

权衡是什么(例如可查询性)


(我最感兴趣的是SQL Server和.NET,但我也想了解其他平台是如何解决这个问题的。)

您将规范化数据库,这实际上会反映您的继承。
它可能会降低舞蹈的性能,但正常化就是这样。您可能需要使用良好的常识来找到平衡。

在数据库中可以设置两种主要的继承类型,即每个实体的表和每个层次的表

每个实体的表是一个具有所有子类共享属性的基本实体表。然后,每个子类都有另一个表,每个表仅具有适用于该类的属性。他们的PK以1:1的比例联系在一起

每个层次结构的表是所有类共享一个表的地方,可选属性可为空。它们也是一个鉴别器字段,它是一个数字,表示记录当前保存的类型

SessionTypeID是鉴别器

每个层次的目标查询速度更快,因为您不需要联接(仅限鉴别器值),而每个实体的目标查询需要进行复杂联接,以便检测某个对象的类型并检索其所有数据


编辑:我在这里显示的图像是我正在处理的项目的屏幕截图。资产映像不完整,因此它是空的,但它主要是显示如何设置它,而不是在表中放置什么。这取决于你;)。会话表保存虚拟协作会话信息,根据所涉及的协作类型,可以有几种类型的会话。

在数据库中建模继承有几种方法。你选择哪一个取决于你的需要。以下是一些选项:

每种类型的表格(TPT)

每个类都有自己的表。基类中包含所有基类元素,从基类派生的每个类都有自己的表,主键也是基类表的外键;派生表的类仅包含不同的元素

例如:

class Person {
    public int ID;
    public string FirstName;
    public string LastName;
}

class Employee : Person {
    public DateTime StartDate;
}
将生成如下表:

table Person
------------
int id (PK)
string firstname
string lastname

table Employee
--------------
int id (PK, FK)
datetime startdate
每个层次结构的表格(TPH)

有一个表表示所有继承层次结构,这意味着有几个列可能是稀疏的。添加了一个鉴别器列,告诉系统这是什么类型的行

鉴于上述类别,您将得到以下表格:

table Person
------------
int id (PK)
int rowtype (0 = "Person", 1 = "Employee")
string firstname
string lastname
datetime startdate
对于行类型为0(Person)的任何行,startdate将始终为空

每种混凝土的表(TPC)

每个类都有自己的完全格式表,没有对任何其他表的引用

给定上述类,您将得到以下表格:

table Person
------------
int id (PK)
string firstname
string lastname

table Employee
--------------
int id (PK)
string firstname
string lastname
datetime startdate

在O-R映射中,继承映射到父表,其中父表和子表使用相同的标识符

比如说

create table Object (
    Id int NOT NULL --primary key, auto-increment
    Name varchar(32)
)
create table SubObject (
    Id int NOT NULL  --primary key and also foreign key to Object
    Description varchar(32)
)
子对象与对象具有外键关系。创建子对象行时,必须首先创建对象行并在两行中使用Id

编辑:如果您还想对行为建模,则需要一个类型表,列出表之间的继承关系,并指定实现每个表行为的程序集和类名

看起来有点过分,但这取决于你想用它做什么

使用SQL ALchemy(Python ORM),您可以执行两种类型的继承

我有过的一个经验是使用单表,并有一个判别列。例如,绵羊数据库(不开玩笑!)将所有绵羊存储在一个表中,而公羊和母羊则使用该表中的性别列进行处理


因此,您可以查询所有羊,并获取所有羊。或者,您可以只通过Ram进行查询,它只会得到Ram。您还可以做一些事情,比如建立一个只能是Ram的关系(即,绵羊的父系),等等。

注意,一些数据库引擎已经提供了类似的本地继承机制。看这张照片

例如,您可以查询上面响应中描述的人员/员工系统,如下所示:

/* This shows the first name of all persons or employees */ SELECT firstname FROM Person ; /* This shows the start date of all employees only */ SELECT startdate FROM Employee ;
table Shape
-----------
int id; (PK)
int color;
int thichkness;
int rowType; (0 = Rectangle, 1 = Circle, 2 = ...)

table Rectangle
----------
int ShapeID; (FK on delete cascade)
int topLeftX;
int topLeftY;
int bottomRightX;
int bottomRightY;

table Circle
----------
int ShapeID; (FK on delete cascade)  
int centerX;
int center;
int radius;
/*显示所有人员或员工的名字*/ 从Person中选择firstname; /*这仅显示所有员工的开始日期*/ 从员工中选择startdate;
这是数据库的选择,您不需要特别聪明

正确的数据库设计与正确的对象设计完全不同

如果您计划将数据库用于除简单地序列化对象之外的任何事情(如报告、查询、多应用程序使用、商业智能等),那么我不推荐任何类型的从对象到表的简单映射

许多人认为数据库表中的一行是一个实体(我用这些术语思考了很多年),但一行不是一个实体。这是一个命题。数据库关系(即表)表示关于世界的一些事实陈述。行的存在表示事实为真(反之,行的缺失表示事实为假)

通过这种理解,您可以看到,面向对象程序中的单个类型可能存储在十几个不同的关系中。并且各种类型(通过继承、关联、聚合或完全不关联而联合)可以部分存储在单个关系中

最好问问自己,你想储存什么事实,你想回答什么问题,你想生成什么报告

一旦创建了正确的数据库设计,那么创建查询/视图就很简单了,这些查询/视图允许您将对象序列化为这些关系

例如:

在酒店预订系统中,您可能需要存储Jane Doe已预订了Seaview Inn 4月10日至12日的房间这一事实。我
table Shape
-----------
int id; (PK)
int color;
int thichkness;
int rowType; (0 = Rectangle, 1 = Circle, 2 = ...)

table Rectangle
----------
int ShapeID; (FK on delete cascade)
int topLeftX;
int topLeftY;
int bottomRightX;
int bottomRightY;

table Circle
----------
int ShapeID; (FK on delete cascade)  
int centerX;
int center;
int radius;