在数据库中存储继承的对象

Eri*_*tas 4 orm database-design relational-database

我试图找出将对象模型中的继承关系映射到关系数据库的最佳方法.例如,考虑以下类结构.

public Class Item 
{
    public String Name{get; set;}
    public int Size {get; set}    
}

public Class Widget:Item
{
    public String Color{get; set;}
}

public Class Doohicky:Item
{
    public String Smell{get; set;}
}
Run Code Online (Sandbox Code Playgroud)

以下是我正在考虑如何将此结构保存到数据库的一些选项.

选项1:所有项目类型的单表

Items Table: ItemID, Name, Color, Smell
Run Code Online (Sandbox Code Playgroud)

这很糟糕,因为它需要NULL值.

选项2:每种项目类型的单独表格

Widgets Table: WidgetID, Name, Color
Doohicky Table: DoohickyID, Name, Smell
Run Code Online (Sandbox Code Playgroud)

这样更好,但列出所有项目会更加困难

选项3:链接表

Items Table: ItemID (PK), Name, Size
Widgets Table: WidgetID (PK), ItemID (FK), Color
Doohicky Table: DoohickyID (PK), ItemID (FK), Smell
Run Code Online (Sandbox Code Playgroud)

我认为这个选项是最好的,因为它阻止我在任何字段中都有Null值,而且它会更容易列出所有Items,和/或创建特定类型的Item(Widgets或Doohickies)列表.

但是,我不确定如何创建Items表与Widgets和Doohickies表之间的关系.我不想在任何表中引用行引用Items表中的相同ItemID.

例如,当我向Widgets表添加一个条目时,如何确保它链接到Items表中具有唯一ItemID的新条目?我应该只跟踪ItemID而不是单独的类型特定ID,如WidgetID和DoohickyID,并使用它来创建Items表和类型特定表之间的一对一关系?

选项4

Items Table: ItemID (PK), Name, Size
Widgets Table: ItemID (PK), Color
Doohicky Table: ItemID (PK), Smell
Run Code Online (Sandbox Code Playgroud)

Bil*_*win 6

您正在描述单表继承,具体表继承类表继承.

有关它们的大量信息,请参阅经典的Martin Fowler书籍企业应用程序架构模式.

您可以做的一件事是确保只有一个子类型可以引用超类型是使用ItemType字段.外键可以引用UNIQUE约束的列以及PRIMARY KEY.所以,你可以添加Items.ItemType,使一个唯一约束了ItemID,ItemType.每个子类型表中的外键引用此两列唯一键.然后,您可以将ItemType每个子类型表中的约束限制为某个值.然后它必须匹配超类型表中的值,该表只能有一个值.

Items Table: ItemID (PK), ItemType, Name, Size
  UNIQUE: (ItemID, ItemType)
Widgets Table: ItemID (PK), ItemType, Color
  FK: (ItemID, ItemType)
  CHECK: ItemType=W
Doohicky Table: ItemID (PK), ItemType, Smell
  FK: (ItemID, ItemType)
  CHECK: ItemType=D
Run Code Online (Sandbox Code Playgroud)