实现DB对象的版本控制

时间:2009-08-16 22:06:54

标签: asp.net linq-to-sql database-design normalization

我很快就会开始研究一个项目(从规范中)让我想起StackOverflow。基本上,它是一个具有用户控制内容的Web应用程序。

让我在脑海里转转的一个功能是版本控制。在StackOverflow上,每个问题和答案都可以有多个修订版。当你只有一种类型的对象(在这种情况下,它的文本)时,这很容易实现。

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

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

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

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

当这种关系成为多对多关系时会变得更加复杂,多个作者可能被列为对一本书有所贡献。

我有许多解决方案,但它们都没有我想要的那么干净(并且至少涉及一些重复的代码/冗余数据存储),尽管我确实看到了这里的共性,我觉得我真的无法最好地提取它,特别是在数据库级别。我不想偏袒给出的答案,所以我不打算立刻给他们。

那么,您将如何在数据库级别设计此系统?我在这里寻找表格规范,并且可能描述了如何使用它们,如果不是很明显的话。对于那些可能相关的答案,我将使用ASP.NET和Linq-to-SQL(我对LTS中的多对多)或实体框架感到满意。

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

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

3 个答案:

答案 0 :(得分:5)

这是数据仓库中常见的问题。他们使用“缓慢变化的维度”。

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

  1. 您必须记录最初定义的作者 - 书籍关系 。这是官方的作者 - 书籍关系。数据仓库人员称之为“无事实的事实表”。这是一对钥匙。

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

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

  4. 请注意,关系(作者预订)是一个事实,不需要版本。这是事实。它没有“改变”。这是真的,或者它被错误地放在数据库中 - 在这种情况下,必须将其删除。事实不需要版本号。

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

    因此,时间是书作者事实的维度。如果这一事实可能发生变化,则适用的时间段将作为事实的一部分进行记录。

    时间维度与版本号不完全相同。它稍微简单一些。它指出,在某一特定时间点,事实确实如此。如果事实发生变化,您会添加一个具有不同时间戳的新事实。

    在特定时间点,您可以找到相关事实和相关维度值。

答案 1 :(得分:1)

我为每张桌子都有一张桌子:即作者和书籍。

表之间存在通常的外键关系(无论是什么)。

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


编辑:

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


  

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

编辑#2:

我还没有实现多对多情况的历史,但我不明白为什么它不会相同,即:

  • 多对多关系是通过BookAuthor表实现的,每个记录只有BookId和AuthorId。
  • 历史关系位于相应的BookAuthorHistory表中。

答案 2 :(得分:1)

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

文档之间也可以有m:n关系。但是,迁移到CouchDB是一个很大的步骤,我不知道从ASP.NET可以访问它的程度。但阅读一些入门教程不​​会有什么坏处。