【问题标题】:Is using a table inheritance a valid way to avoid using a join table?使用表继承是避免使用连接表的有效方法吗?
【发布时间】:2010-12-17 04:12:55
【问题描述】:

我一直在为这个项目遵循主要是 DDD 方法,因此,像任何 DDD 一样,我首先创建了我的域模型类。我的意图是将这些 POCO 用作我的 LINQ-to-SQL 实体(是的,它们不是纯 POCO,但我可以接受)。我已经开始创建数据库架构和外部映射 XML 文件,但是在建模实体的关系和关联时遇到了一些问题。

一个工件代​​表一个文档。工件可以与任务或案例相关联。 Case 实体如下所示:

public class Case 
{
     private EntitySet<Artifact> _Artifacts;
     public IList<Artifact> Artifacts
     {
          get
          {
               return _Artifacts;
          }
          set
          {
               _Artifacts.Assign(value);
          }
     }
     .
     .
     .
}

由于 Artifact 可以与 Case 或 Task 关联,因此我可以选择使用 Artifact 类的继承来创建 CaseArtifact 和 TaskArtifact 派生类。然而,这两个类之间的唯一区别是是否存在案例字段或任务字段。当然,在数据库中,我将有一个表 Artifact,其中包含类型鉴别器字段以及 CaseId 和 TaskId 字段。

我的问题:这是解决此问题的有效方法,还是为每个关联(总共 2 个新表)创建一个连接表是更好的方法?

【问题讨论】:

    标签: sql-server architecture .net-3.5 domain-driven-design poco


    【解决方案1】:

    我可能会使用两个表 - 它使引用完整性 - PK/FK 在数据库中的处理更简单一些,因为您不必有基于选择器列的复杂约束。

    (回复您的评论 - 我的空间用完了,所以在这里发布作为编辑)我的总体理念是数据库应该使用数据库最佳实践建模(保护您的边界并确保数据库一致性,使用尽可能多的 RI 和约束,通过 SP 提供所有访问,根据需要记录活动,控制所有访问模式,在必要时使用触发器)并且对象模型应该使用 OOP 最佳实践建模,以提供强大且一致的 API。处理阻抗失配是您的 SP/数据访问层的工作。

    如果您只是将设计良好的对象模型持久化到数据库中,那么在不通过对象模型 - 这对于某些应用程序来说很好,通常不适用于我的应用程序。

    如果您只是在应用程序中模仿设计良好的数据库结构,而不提供丰富的 OO API,那么您的应用程序将难以维护,并且内部结构将难以处理 - 通常非常程序化、僵化且具有很多代码重复。

    【讨论】:

    • 所以您认为拥有两个附加连接表所增加的复杂性低于使用 STI 的复杂性?由于我使用的是 L2S,这意味着我的类中有一个 EntitySet,而不是直接引用,对吧?
    • 查看我的编辑。我通常有一个不模仿数据库的 OO 模型。在没有足够了解的情况下,我可能会让 Artifact.Case 或 Artifact.Task 有效(XOR),或者有两个类 CaseArtifact 和 .Case 和 TaskArtifact 和 .Task 和 Case.Artifacts 是与 Case 相关联的所有工件的集合,并且Task.Artifacts 是与任务关联的所有工件的集合。
    • 您在编辑中提出了一些非常好的观点。提供丰富的 API 是我设计的中心目标之一。不过,在永远的毁灭公爵之前释放一段时间也很重要。我已经决定我必须对我的领域模型做出一些妥协,以便“让它与 L2S 一起工作”。生成的域模型比我特别关心的更接近 DB 模式,但希望仍然 OO 足以公开丰富的 API。我按照建议使用连接表,将它们放在项目的不同文件夹中,以帮助将它们与“真实”域对象分开。
    • 好动作。我总是从各个方面迭代构建——UI 需求、模型需求和 DB 需求。我总是对过度使用特定工具持谨慎态度 - 例如。 ORM 或 LINQ2SQL 或其他任何东西——它们都是有漏洞的抽象,最终会崩溃——希望它们的崩溃总是远远超出你的要求,但注意这一点总是很重要的,因为当你看到火车时,你有更多的时间未来,您可以更好地管理您的产品路线图。
    • 没错。我当前的项目实际上不允许进行通常会发生的那种迭代构建,但这就是程序化集成测试的用途!能够在编写 OR 映射时对其进行测试,并且在我更改架构时确切知道需要修复什么,这真是太棒了
    【解决方案2】:

    我会考虑在 casetask 之间找到共同点,因为没有更好的词,我们称之为“CaseTask”,然后再分-从那个打字(继承)。之后,您将文档附加到超类型。

    更新(评论后):
    然后我会考虑这样的事情。每个文档都可以附加到多个案例或任务中。



    【讨论】:

    • 案例和任务之间唯一真正的领域共同点是两者都可以附加文档(“工件”)。事实上,任务与案例间接相关(通过集合类)。
    • 那么一个案例有很多任务?您能解释一下案例和任务之间的关系吗?
    • 当然。案例具有与之关联的工作流。工作流是任务的集合,以及一些其他属性。工作流与案例相关联,但工作流中的各个任务不相关,因为它们包含在工作流本身中。
    • 您帖子的更新看起来不错,并且非常接近您的反馈和 Cade 的回答我的想法。变得复杂的地方是如何在我的 POCO 类和生成的 L2S 映射中对其进行建模......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多