C# 在数据库中保存数据更改的历史记录

C# 在数据库中保存数据更改的历史记录,c#,sql,C#,Sql,数据库中某一行中数据的每次更改都应该将前一行数据保存在某种历史记录中,以便用户可以回滚到前一行数据状态。这种方法有什么好的实践吗?尝试使用DataContract以及序列化和反序列化数据对象,但使用复杂对象时会变得很混乱 更清楚地说: 我正在使用NHibernate进行数据访问,希望远离数据库依赖关系(用于使用SQLServer2005进行测试) 我的目的是提供数据历史记录,以便每次用户都可以回滚到以前的一些版本 使用示例如下: 我有一篇新闻文章 有人对那篇文章做些修改吗 主编辑看到这条新闻有

数据库中某一行中数据的每次更改都应该将前一行数据保存在某种历史记录中,以便用户可以回滚到前一行数据状态。这种方法有什么好的实践吗?尝试使用DataContract以及序列化和反序列化数据对象,但使用复杂对象时会变得很混乱

更清楚地说:

  • 我正在使用NHibernate进行数据访问,希望远离数据库依赖关系(用于使用SQLServer2005进行测试)

  • 我的目的是提供数据历史记录,以便每次用户都可以回滚到以前的一些版本

  • 使用示例如下:

    • 我有一篇新闻文章
    • 有人对那篇文章做些修改吗
    • 主编辑看到这条新闻有一些打字错误
    • 它决定回滚到以前的有效版本(直到更正最新版本)

    我希望我给了你有效的信息。

    你使用的是什么数据库系统?如果您使用的是与ACID(原子性、一致性、隔离性、耐久性)兼容的数据库,难道不能使用内置回滚功能返回到以前的事务吗?

    当主表更改称为审核表时,存储更改的表。您可以通过多种方式执行此操作:

    • 在数据库中使用触发器:我建议使用这种方法,因为如果没有记录,数据就无法更改。执行此操作时,您必须考虑3种类型的更改:添加、删除和更新。因此,您需要在这三种情况下都能工作的触发器功能
    还要记住,一个事务可以同时修改多个记录,因此您应该处理完整的修改记录集,而不仅仅是最后一条记录(大多数人后来才意识到这一点)

    在触发器执行完成之前,控件不会返回给调用程序。因此,您应该尽可能轻松快速地编写代码

    • 在中间层使用代码:这种方法将允许您将更改保存到其他数据库,并可能减轻数据库的一些负载。然而,运行UPDATE语句的SQL程序员将完全绕过您的中间层,您将没有审计跟踪
    审计表的结构

    您将有以下列:
    自动编号主键、时间戳、ActionType+原始表中的所有列

    我过去曾通过以下方式做到这一点:

    表格结构:
    自动编号主键、时间戳、操作类型、表名、OriginalTableStructureColumns

    此结构意味着您为保存的每个数据表创建一个审核表。数据保存和重建相当容易。我建议采用这种方法。 名称-值对:
    自动编号主键、时间戳、ActionType、TableName、PKColumns、ColumnName、OldValue、NewValue


    此结构允许保存任何表,但必须为触发器中的每一列创建名称-值对。这是非常通用的,但价格昂贵。您还需要编写一些视图,通过取消激活数据来重新创建实际行。这会变得单调乏味,并且通常不是遵循的方法。

    您可以使用触发器来实现这一点。 下面是一个例子


    一种方法是使用本机支持此功能的数据库,如。我通常不会建议“更改您的DB服务器以获得这一功能”,但由于您在问题中没有指定DB服务器,我认为您的意思是这是开放式的,并且服务器中的本机支持是此功能的最佳实现之一。

    Microsoft在SQL server 2008中引入了新的审核功能。这里有一篇文章描述了一些功能和设计目标,无论您选择哪种方法,这些功能和目标都可能有所帮助


    保存序列化数据最终总是会变得一团糟,你应该远离这一点。最好的做法是创建一个与主表具有相同列的并行“版本”表

    例如,如果您有一个名为“book”的表,其中包含“id”、“name”、“author”列,则可以添加一个名为“book\u version”的表,其中包含“id”、“name”、“author”、“version\u date”、“version\u user”列

    每次插入或更新表“book”上的记录时,应用程序也会插入“book\u version”


    根据您的数据库系统和从应用程序访问数据库的方式,您可能能够完全自动化此操作(cfr原则中的可版本插件)

    我使用NHibernate.Enverse很好地解决了这个问题

    对于那些感兴趣的人,请阅读以下内容:

    这将取决于用户希望回滚的未来距离,但如果是针对取消/确定类型的场景,我同意。我正试图避免数据库服务器依赖,并用C#解决这一问题。回滚可以回滚到历史上的任何版本。我试图避免数据库服务器依赖,并用C#解决这个问题。如果我决定依赖SQL server,上面的答案非常好。如果这是您的意图,您最好编辑您的问题并明确您的限制。“我试图避免依赖数据库服务器,并用C#解决这个问题。如果我决定依赖SQL server,上面的答案非常好。”这是错误的方法。在数据库之外的任何地方进行审计都是非常糟糕的做法。数据库更改的来源比应用程序多得多。在其他任何地方进行这种审计都会失去对更改(特别是来自内部用户的恶意更改)的跟踪。HLGEM,+1是你字面上说的,但他的问题非常模糊,他可能实际上不想要“审计”功能,而是想要某种特定于应用程序的“撤销”很难从他写的那一点来判断。很抱歉给你提供的信息太少。我只需要跟踪所有数据
     AutoAudit is a SQL Server (2005, 2008)
     Code-Gen utility that creates Audit
     Trail Triggers with:
    
         * Created, Modified, and RowVerwsion (incrementing INT) columns to table
         * view to reconstruct deleted rows
         * UDF to reconstruct Row History
         * Schema Audit Trigger to track schema changes
         * Re-code-gens triggers when Alter Table changes the table