【问题标题】:Storing inherited objects in a database将继承的对象存储在数据库中
【发布时间】:2010-09-09 00:28:16
【问题描述】:

我正在尝试找出将对象模型中的继承关系映射到关系数据库的最佳方法。例如考虑下面的类结构。

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;}
}

以下是我正在考虑的几个选项,用于将此结构保存到数据库中。

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

Items Table: ItemID, Name, Color, Smell

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

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

Widgets Table: WidgetID, Name, Color
Doohicky Table: DoohickyID, Name, Smell

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

选项 3:链接表

Items Table: ItemID (PK), Name, Size
Widgets Table: WidgetID (PK), ItemID (FK), Color
Doohicky Table: DoohickyID (PK), ItemID (FK), Smell

我认为这个选项是最好的,因为它可以防止我在任何字段中使用 Null 值,而且它可以更轻松地列出所有项目,和/或创建特定类型项目的列表(小部件或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

【问题讨论】:

    标签: database-design orm relational-database


    【解决方案1】:

    您正在描述Single-Table InheritanceConcrete Table InheritanceClass Table Inheritance

    请参阅经典的 Martin Fowler 书籍Patterns of Enterprise Application Architecture,了解有关它们的大量信息。

    要确保只有一个子类型可以引用超类型,您可以做的一件事是使用ItemType 字段。外键可以引用 UNIQUE 约束的列以及 PRIMARY KEY。因此,您可以添加Items.ItemType 并对ItemIDItemType 进行唯一约束。每个子类型表中的外键引用这个两列唯一键。然后您可以将每个子类型表中的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
    

    【讨论】:

    • 啊,这很有帮助。我绝对想遵循“类表继承”模式。
    【解决方案2】:

    如果您在设计时牢记当前的课程,出于上述原因,我希望您的选项 3 作为首选选项。

    关于您的疑问:

    However, I'm not sure how to create the relationship between the Items table and the
    Widgets and Doohickies tables. I don't want to end up with row in either table 
    referencing the same ItemID in the Items table. 
    

    上面比尔的建议绝对是一个不错的选择。我没想到的东西:-) 但是,我认为这是一种关系,您可以在应用程序代码本身或使用插入触发器中强制执行。

    然而,我担心的是尝试在数据库级别模拟继承本身。

    如果预期子类的数量会在一段时间内增长,那么这种 DB 设计可能会变得非常难以维护。

    除了:

    Items Table: ItemID (PK), Name, Size        
    Widgets Table: WidgetID (PK), ItemID (FK), Color        
    Doohicky Table: DoohickyID (PK), ItemID (FK), Smell        
    

    添加如下新类的可能性有多大?

    DontDoHicky Table : DoohickyID (PK), ItemID (FK), Smell, **TASTE**        
    MidWidget Table : WidgetID (PK), ItemID (FK), Color , **Height**        
    MidDoHicky Table : WidgetID (PK), ItemID (FK), **Height**, **Smell**
    

    这当然是经典的OO继承问题。 如果您希望应用程序在一段时间内像这样增长,并且可能需要事先在数据库级别进行计划,您可能更喜欢使用更通用的方法

    Items Table: ItemID (PK), Name, Size, **ItemType**        
    **ItemAttributes Table : ItemID (PK), AttributeID, AttributeName, AttributeValue**    
    

    这将允许您轻松实施 1:1 映射的约束,并允许您使用 AttributeName 轻松查询所有属性,只要它们是标准的。

    这可能是老式的方法,不是非常面向对象,但根据未来的灵活性,它可能更适合。

    【讨论】:

      【解决方案3】:

      您是否考虑过NoSQL 解决方案,例如RavenDBMongoDB?如果您的需求不是纯粹的关系,非关系解决方案可能会大大简化事情。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-16
        • 2013-01-10
        • 1970-01-01
        相关资源
        最近更新 更多