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

实现数据库对象的版本控制

  •  5
  • JoshJordan  · 技术社区  · 17 年前

    我将很快开始一个项目的工作,这个项目(从规范中)让我想起了stackoverflow。基本上,它是一个有用户控制内容的Web应用程序。

    其中一个让我在脑海中转来转去的特性是版本控制。在StackOverflow中,每个问题和答案可以有多个修订。当您只有一种类型的对象(在本例中,是它的文本)时,实现这一点非常简单。

    所以,对于我的简单页面,我已经设置好了。

    当我考虑需要在版本控制下的一些对象具有关系时,问题就出现了。为了提供一个具体的例子,让我选择一个随机的肛门域:

    假设我正在实现一个类似wiki的网站来跟踪书籍/作者信息。 网站的主要焦点是创建和更新“作者”页面,作为文本,这非常简单(如上所述)。但是,让我们在作者和书籍之间添加一对多的关联(换句话说,书籍将是单独的对象,显然一个人可以创作许多书籍)。每本书都有一个从作者页面到该书信息页面的链接。

    对于用户来说,描述作者的基于文本的“摘要”与作者与其作品之间的链接几乎没有区别。因此,我们需要对作者页面、书籍页面和 和 作者与书籍之间的联系。换句话说,用户应该能够编辑、查看和回滚作者页面、书籍页面以及两者之间的关联。

    当这种关系变成“多对多”时,这就变得更加复杂了,在这种情况下,可以将多个作者列为一本书的作者。

    我想到了许多解决方案,但它们都没有我想要的那么干净(至少涉及到一些重复的代码/冗余数据存储),而且,尽管我在这里看到了所有地方的共性,但我觉得我还没有真正能够最好地提取它,特别是在数据库级别。我不想对给出的答案产生偏见,所以我不会马上给出答案。

    那么,您如何在数据库级别设计这个系统呢? 我在这里寻找表的规格,如果不明显的话,可能还需要描述一下您将如何使用它们。对于那些可能与之相关的答案,我将使用ASP.NET和Linq to SQL(我对LTS中的多对多比较熟悉)或实体框架。

    编辑: 为了澄清,我了解基本的数据库设计、规范化、多对多映射表等。我正在寻找一个针对这种特定情况的干净解决方案。

    编辑2: 我正在寻找一个可归纳的解决方案,因为系统中可能有更多的子对象,而不仅仅是书籍。作者可能与其他作者、杂志、事件等有关。如果我为每个人单独实现历史,我觉得我在重复很多工作。

    3 回复  |  直到 17 年前
        1
  •  5
  •   S.Lott    17 年前

    这是数据仓库中一个非常常见的问题。他们使用“慢慢改变尺寸”。

    但是,如果要尝试使用“版本化”数据,则必须有一些规则。

    1. 你必须记录作者与书的关系 如最初定义 . 这就是作者与书的正式关系。数据仓库人员称之为“无事实事实数据表”。这是一对钥匙。

    2. 书籍是书籍作者事实的一个维度。这本书可以换。有许多缓慢变化的维度算法。您只能保留最新的、历史记录表与当前表分开。将历史记录和当前记录保存在一个带有标志的表中,以区分当前记录和历史记录。

    3. 作者是书作者事实的一个维度。作者可以改变。同样,还有许多SCD算法。继续阅读选择。Ralph Kimball的数据仓库工具包提供了更多信息。

    请注意,这种关系(作者与书籍)是事实,不需要版本。这是事实。它不会“改变”。它要么是真的,要么是错误地放在数据库中——在这种情况下,必须删除它。事实不需要版本号。

    在更复杂的星型模式中,您的事实具有度量标准。价格、销售量、成本、利润等也记录在事实表中。这些信息可能随时间而变化。因此,对于每个事实,您几乎总是有一个时间维度。

    因此,时间是书作者事实的一个维度。如果此事实可以更改,则将适用的时间段记录为事实的一部分。

    时间维度与版本号不完全相同。稍微简单一点。它指出,在特定的时间点,事实是真实的。如果事实发生变化,您可以用不同的时间戳附加一个新事实。

    您可以在给定的特定时间点上定位相关事实和相关维度值。

        2
  •  1
  •   ChrisW    17 年前

    我为每张桌子都准备了一张桌子:即作者和书。

    表之间通常有外键关系(不管是什么关系)。

    每个表也有一个历史表,即authorhistory和bookhistory。这些历史记录表包含旧的/过时的记录版本(例如,每个已删除和/或已编辑的作者记录)。与历史记录表之间没有外键关系。


    编辑:

    对于每个表,有些功能是相似的:例如,无论哪个表,更新记录都意味着将记录的旧副本存储在相应的历史表中。我使用数据库触发器(更新和删除每个表的触发器)实现此功能;因为我使用的数据库引擎支持触发器,这使它对应用程序透明。这些触发器中的代码在一个表和下一个表之间是相似的(只有表的名称和字段名称列表在一个表和下一个表之间有所不同)。


    多对多的情况怎么样?这更困难,因为实际上你可能没有记录将作者映射到一本书,但之前有一本书,需要将其作为历史项目显示出来。

    编辑第2页:

    我还没有实施过多对多情况的历史,但我不明白为什么会不一样,即:

    • 多对多关系是通过存在一个bookauthor表来实现的,每个表的记录都只是bookid加authorid。
    • 历史关系位于相应的BookAuthorHistory表中。
        3
  •  1
  •   fbuchinger    17 年前

    听起来几乎是CouchDB的理想用例。使用此面向文档的数据库,您可以免费获得修订(除非您的数据库配置不同,否则每个文档都会自动重新修订)。

    文件之间也可能存在m:n关系。但是,迁移到CouchDB是一个很大的步骤,我不知道从ASP.NET访问它有多好。但是阅读一些入门教程不会有什么伤害。

    推荐文章