【问题标题】:"One-to-many" modeling question“一对多”建模问题
【发布时间】:2010-07-08 01:30:22
【问题描述】:

以下建模的最佳方法是什么...

假设我有两个对象:AgencyPublisher,它们都与Employee 具有一对多的关系。这是真正的一对一关系,因为每个Employee 只能用于一个Agency 或一个Publisher。让我们进一步假设我不能介绍 持有一对多关系的超类型(例如Employer)。

我的首选解决方案是在Employee 中有一个外键,它可以链接到AgencyPublisher 的主键(我的所有主键都是在数据库中唯一的64 位ID)。但是,现在我无法映射双向关联,除非在 Employee 中指明这是 Agency 还是 Publisher 关系。

我的另一个选择是使用两个表,AgencyEmployeePublisherEmployee,然后可以将它们链接为传统的 1 对 n 双向关联。

您认为在这种情况下的最佳做法是什么?

更新:感谢您在如此短的时间内做出如此出色的回应!您如何看待以下解决方案:Employee 中的外键同时用于AgencyPublisher,例如agency_idpublisher_id

【问题讨论】:

    标签: sql database-design orm data-modeling


    【解决方案1】:

    最好的做法可能是引入一个 Employer 类。

    另一方面,将 Employee 分为 AgencyEmployee 和 PublisherEmployee 是一件坏事。

    如果不能介绍 Employer,我会在 Employee 中指明雇主类型(Agency 或 Publisher)。

    对更新后问题的回应:

    这是一个选项,但雇主类型更好,因为:

    1. 您将来可能希望添加其他雇主类型
    2. Employees 表的每一行都会有一个空字段。

    【讨论】:

    • 我同意最佳实践和 Bad Thing 调用,但我认为从规范化的角度来看,使用 EmployeeID 作为 PK、EmployerID 和 EmployerType 的第三张表会更好。
    • @Harper:没错,但从务实的角度来看,这意味着另一个连接(和多列主键)。
    【解决方案2】:

    这样的声音可以建模为ternary relationship。看看您是否喜欢这篇 MSDN 文章中采用的方法。

    【讨论】:

      【解决方案3】:

      我用过这种方法:

      Employee.EmployerType('AGENCY' 或 'PUBLISHER')

      Employee.EmployerID(AgencyID 或 PublisherID)

      它工作正常,但是您需要在很多 SQL 中使用 case 语句。如果你使用 ORM,你也会失去 FK 关系。

      我正在将我的大部分代码移至 n:m 关系,以便我可以利用我们的 ORMs FK 支持。

      【讨论】:

        【解决方案4】:

        显然雇主实体是首选,但除此之外......

        拥有 AgencyEmployee 和 PublisherEmployee 表意味着很难确定员工是否属于一个类别。

        因此,我会将 EmployerType 列添加到员工表中;它为您的后续 SQL 查询增加了一点额外的复杂性,但它在您给定的约束范围内工作。

        出于兴趣,您为什么可以添加 AgencyEmployee 和 PublisherEmployee 表,但不能添加 Employer 表?只是好奇...

        【讨论】:

          【解决方案5】:

          Can Berk Güder 获得 +1。

          从技术上讲,引入 Employer 超类型意味着您引入具有 Agency 和 Publisher 共有的所有属性的 Employer 关系、带有 Employer 键和所有 Agency 特定属性和 Employer 键的 AgencySpecific(不确定如何调用)关系作为外键,然后 Agency 作为查询或视图,将 AgencySpecific 与 Employer 连接起来,对于 Publisher 也是如此。

          将 Agency 和 Publisher 数据分布在您每次都必须加入的两个表中可能有点麻烦,但另一种方法是两次编写与员工相关的大部分查询,一次使用 Agency,一次使用 Publisher,然后手工制作他们的工会以结合结果。 (我还没有看到一个查询构建器可以帮助处理这样的基本内容。)我不得不为一个使用“无超类型”方法的项目做这件事,我不想再做一次了。

          如果你问我,顺便说一句,三元关系甚至 n 对 n 关系都不是好的设计实践。仅使用函数(即 1 对 n 和 1 对 1),例如约束变得更容易制定。

          【讨论】:

            【解决方案6】:

            我个人的偏好是有一个你明确认为不能使用的表(代理和出版商的超类型;雇主)

            一个简单的替代方法是不强制执行外键约束。这不一定有问题,只要对数据结构的所有修改都是通过您控制的存储过程完成的。

            我的最终偏好与您的建议类似,即为 AgencyEmployees 设置一个表,为 PublisherEmployees 设置一个表。但我会把它分开一步......

            Table1: Agency              (id, name, etc)
            Table2: Publisher           (id, name, etc)
            Table3: Employee            (id, name, etc)
            Table4: AgencyEmployees     (agency_id, employee_id)
            Table5: PublisherEmployees  (publisher_id, employee_id)
            


            我这样做的一个原因是让这个时间依赖变得微不足道。员工开始、离开和在公司之间移动。以下对上述内容的轻微修改将允许您跟踪...

            Table1: Agency              (id, name, etc)
            Table2: Publisher           (id, name, etc)
            Table3: Employee            (id, name, etc)
            Table4: AgencyEmployees     (agency_id,    employee_id, start_date, leave_date)
            Table5: PublisherEmployees  (publisher_id, employee_id, start_date, leave_date)
            

            这不会在任何时候为每位员工强制执行 1 个雇主,但可以通过您的存储过程、GUI 等强制执行...

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-07-11
              • 2011-03-06
              • 1970-01-01
              • 2010-11-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多