代码之家  ›  专栏  ›  技术社区  ›  David

父类型表-是否可以多重继承?

  •  1
  • David  · 技术社区  · 14 年前

    有可能这个问题要么有一个简单的答案,这是一个标准的实践,要么没有答案,因为它不能做一个简单的原因,否则只是一个有趣的思考练习。我现在坐在最后一个选项上,但希望第一个…

    假设我想在我的数据模型中创建一个实体的“组”或“类”。通常,我会使用这样的父类型表:

    DrivableEntity
    ----------
    ID (PK, auto-increment)
    Type (int or otherwise some kind of enum)
    
    Car
    ----------
    ID (PK, FK to DrivableEntity)
    (car-specific fields)
    
    Bike
    ----------
    ID (PK, FK to DrivableEntity)
    (bike-specific fields)
    

    然后,对于每个子表,我的插入可能会经历外部看起来像正常的CRUD过程,但内部插入到 DrivableEntity 然后使用范围标识插入到预期的表中。

    作为一个程序员而不是数据建模者,这让我想到了对象继承。对于直接继承来说,这是伟大的。可以将公共数据/任务抽象为一级,可以保持LISKOV替换等,但在数据模型中是否可能有多重继承?

    我主要是C开发人员,所以我开始从接口的角度思考问题。如果我想公开“实现”的表怎么办? IDrivable 和/或 ITowable 等等,这样的事情是可能的吗?以前有人做过类似的事吗?

    4 回复  |  直到 8 年前
        1
  •  1
  •   ulty4life    14 年前

    通常,数据模型的两种方法对于您所描述的内容都很好地工作。

    您已经描述的模型是一种方法,并且具有非常“整洁”的好处。如果表中有大量的列,它的工作效果尤其好,因此单个对象的大小不会变得太大或太宽。

    DrivableEntity
    ----------
    ID (PK, auto-increment)
    Type (int or otherwise some kind of enum)
    
    Car
    ----------
    ID (PK, FK to DrivableEntity)
    (car-specific fields)
    
    Bike
    ----------
    ID (PK, FK to DrivableEntity)
    (bike-specific fields)
    

    另一种方法是在一个表中保持所有列都可以为空,并用类型指示符标记每一行。这种方法可以很快变得杂乱无章,但对于简单的案例来说开销要小得多。

    您可以在原始模型中为继承或接口建模,只需向其中一个“派生”实体添加另一个外键列即可。例如:

    FlyableEntity
    -------------
    ID (PK)
    ... flyable attributes
    
    FlyingCar (implements/inherits IDrivable and IFlyable)
    -------------
    DrivableEntityID (PK, FK)
    FlyableEntityID (PK, FK)
    ... add flying car attributes
    
    or:
    
    FlyingCar (inherits from Car)
    -------------
    CarID (PK, FK)
    FlyableEntityID (FK)
    ... add flying car attributes
    
        2
  •  1
  •   Community CDub    9 年前

    戴维

    实体框架具有使用继承的能力。 This is good overview of inheritance in the Entity Framework . 您可以使用poco和ef创建自己的接口来提供对数据的访问。

    您描述的情况实际上不是多重继承,因为您有一个基表/实体和一个派生表/实体。要在EF中对此进行建模,需要创建一个基本实体,然后创建每个子实体。此时,可以将每种类型的子实体属性映射到正确的表中。

    也就是说,插入/更新/删除逻辑将变得非常复杂。实体框架可能会遇到复杂模型的问题。

    我想问的是,你为什么这么做?如果要在类型之间共享公共数据,我建议在服务器上创建将父表与子表联接起来的视图。它将更快,并且您可以使用 instead of trigger 这将使SQL更加容易,因为数据访问和数据存储之间存在明显的分割。

    这有道理吗?

    埃里克

        3
  •  0
  •   Michael Riley - AKA Gunny    14 年前

    您可以创建视图来解决这个问题。

    可视驾驶汽车
    可视驾驶自行车
    观景台

    然后将这些视图组合成一个超级视图,使用一个联合将可操纵实体和可拖动实体组合在一起。你只能包括那些在两者中都很常见的专栏。相似但不同的名称需要规范化:

    CREATE VIEW vrDiveTow
    AS
    
    SELECT
    viewDriveableCar.CarId as ID,
    ... other attributes
    
    UNION
    
    SELECT
    viewTowableCar.TowableId as ID,
    ... other attributes
    UNION
    

    大骗局 . SQL使用可以缓存的查询计划来生成结果。如果SQL的查询计划是围绕查询“seven up”而构建的,并且您正在筛选“coke”,那么查询计划无效,实际使用的是完整的表扫描。

        4
  •  0
  •   Pavel Urbančík    14 年前

    子类型是可能的,但也不鼓励。数据库是它们自己的世界,您不应该试图将OOP原则带入这个世界。很多人尝试过,很多人失败了。如果您试图用OOP术语来考虑数据库“对象”,您的数据库将受到影响。

    推荐文章