C# 是否有用于撤消/重做数据库行更改的库/框架?

C# 是否有用于撤消/重做数据库行更改的库/框架?,c#,java,sql-server,database,undo-redo,C#,Java,Sql Server,Database,Undo Redo,可能是我的头衔不清楚。我正在寻找数据库表上的某种版本控制,就像subversion对文件的版本控制一样,就像wiki一样 我想跟踪更改日志。 我想提取并反向运行差异。(像“svn合并-r 101:100”一样撤消)。 我可能需要对历史进行索引搜索 我读过“”,但它与“模式”有关。有什么东西我可以重复使用而不用重新发明轮子吗 编辑: 例如,银行账户交易。我在表中更新了“余额”(和其他)列。用户将在10天后发现错误,并希望在不更改其他事务的情况下取消/回滚特定事务 我如何在应用程序级别优雅地完成它?

可能是我的头衔不清楚。我正在寻找数据库表上的某种版本控制,就像subversion对文件的版本控制一样,就像wiki一样

我想跟踪更改日志。 我想提取并反向运行差异。(像“svn合并-r 101:100”一样撤消)。 我可能需要对历史进行索引搜索

我读过“”,但它与“模式”有关。有什么东西我可以重复使用而不用重新发明轮子吗

编辑: 例如,银行账户交易。我在表中更新了“余额”(和其他)列。用户将在10天后发现错误,并希望在不更改其他事务的情况下取消/回滚特定事务


我如何在应用程序级别优雅地完成它?

迂腐的观点。您的银行账户示例无法通过审计员/监管机构


帐户中的任何错误条目都应保留在那里以备记录。将对该账户应用相等和相反的更正交易。实际上是回滚原始事务,但留下非常明显的原始错误及其更正痕迹。

Martin Fowler在中介绍了该主题。仍然是模式,而不是实际的框架,但他展示了示例数据以及如何使用它。

您可以对要跟踪的每个记录使用修订方法。这将涉及为记录的每次修订保留表中的一行。这些记录将通过共享的“ID”绑定在一起,并可在“修订状态”上查询(例如,获取最新的“批准”记录)。

在应用层中,只要记录了所有必要的信息,就可以单独处理这些记录,并在需要时回滚到早期状态

[ID] [Revision Date] [Revision Status] [Modified By] [Balance]
1     1-1-2008         Expired           User1         $100
1     1-2-2008         Expired           User2         $200
2     1-2-2008         Approved          User3         $300
1     1-3-2008         Approved          User1         $250

根据您对James Anderson的评论,我会让用户界面在取消交易时编写一个新的插入。它将向表中插入一条新记录,该记录的值与被取消的事务的值相同,只是该值将是负数而不是正数。如果您有一个结构,其中包含一些定义事务用途的内容,我会让它说是取消的,以及它正在取消的事务的记录号。

我会采用双时态数据库设计,它将为您提供执行和回滚所需的所有数据,这是否意味着插入更多行或只是删除后面的修改

这样的数据库设计有相当多的微妙之处,但有很多关于这个主题的好书:

Richard T.Snodgrass在SQL中开发面向时间的数据库应用程序

可在此处下载:

使用数据库事务将是一个坏主意,因为它将在数据库中创建锁-基本上数据库事务应该尽可能短


应用层中的任何内容,除非其本身具有某种持久性机制,否则都无法在应用程序重新启动后继续运行(尽管这可能不是一项要求)。

根据各种注释,解决问题的可能方法是创建一个“日期有效”表

基本上,可以向每个表中添加valid from date和valid to date列

“当前”记录的有效截止日期应始终为“2999-12-31”或某个仲裁高值。 当值更改时,您将“有效日期”更改为当前日期并插入 有效起始日期为今天、有效截止日期为“2999-12-31”的新行复制旧行中的所有列(如果未更改)

可以使用创建视图 “从表中选择除有效xx日期以外的所有列,其中有效日期='2999-12-31'”

这将允许所有当前查询保持不变

这是数据仓库环境中的一种非常常见的技术,对于生效日期很重要的汇率之类的东西来说也是如此


撤销逻辑应该是显而易见的

虽然我在使用触发器和行版本之前设置了完整的撤消/审核历史记录,但我不知道有什么特定的模式

有几个MS Sql应用程序可以让您浏览日志并查看实际更改

我在MS SQL 2000中使用了一个名为Log Navigator的工具,该工具可以让我撤销一个特定的历史事务,但现在找不到它

并提供查看日志的工具,但我认为这两种工具都不允许您回滚日志


我认为最好的方法是在编写应用程序时牢记这一点,您在这里已经有了一些关于如何做的好建议。

这就是我想要的。我不打算取消该提交,但允许我跟踪和撤消(例如,使用另一个“svn提交”进行“svn合并-r 101:100”),但我如何在自己的应用程序上优雅地实现它?至少在Oracle中,设置一个奇怪的大值是不好的,因为它会混淆optomizer。NULL通常更好。我读过开发面向时间的数据库应用程序(在我发布的答案中有链接)。这里解释说,有很多原因,为什么使用null是个坏主意,主要是因为它增加了查询的复杂性。你可能想看看这里:我不是在问我如何才能做到这一点。我在问是否有任何代码可以重用。修订Staus列对我来说似乎没有必要,如果有多行具有相同的ID,则可能会得出这样的结论:只有具有最长/最新修订日期的行被批准,而所有其他行都已过期?