4

我正在寻找一种很好的方法来跟踪对对象所做的每一个更改。

我们正在构建一个自定义框架,我们需要了解谁在何时更改了哪个对象以及可能更改了什么的历史(某种程度)。

在这种情况下有什么好的做法?

扩展保存/更新方法以写入“日志”?我应该尝试使用 log4net 还是某种日志扩展?

我担心扩展保存/更新/例程的开销。

编辑:是的,我需要至少看到一个月的变化,客户有时会抱怨数据丢失,他们“忘记”他们删除了它......

Edit2(为了更好地理解,在评论中询问了问题):历史记录应该存储在 db(ms sql)中,我不喜欢在每个类的每个操作中添加日志记录。所有类都继承自我的基类,它提供保存、加载、更新、删除等功能...感谢您的进一步回答/评论 :)

4

4 回答 4

2

您基本上是在寻找审计解决方案,对吧?我知道 Hibernate 使用一个名为 Hibernate Envers 的插件项目来实现它的功能。我能找到的最快的就是这篇博文。至于 NHibernate,我相信正在将 Envers 移植到 NHibernate 上,以便为 .NET 社区利用此功能。

我认为在深入研究单独的解决方案之前,找出 ETA 是值得的。如果您可以将它内置到您的 ORM 中,那就太好了,对吧?;-)

只是快速检查了一下,我认为Tuna Toksoz正在研究它,至少根据他的 Twitter 提要。

于 2009-08-27T12:42:46.643 回答
0

假设您使用的是关系数据库,您可以简单地对插入、更新和删除事件的触发器进行编码,以在另一个表中写入一个操作或其他操作。

据我说,使用与记录的原始数据表具有相同定义的历史表的想法也是一个好主意。这使您可以尽可能地保持原始表的轻量级,从而提高 DQL 在数据库中表上的性能,并且在将 Delete 事件跟踪到意外删除的记录时,您无需获取每条记录由用户。

另一种方法是,根据每天处理的行数,您可以简单地将字段标记为真或假,无论它是否被删除,并添加一个应该保存当前执行操作的列。假设您将数据库配置为使用 Active Directory,以便您可以精确识别当前用户。

在写作的时候,我突然想到了另一个想法。您可能已经自己考虑过了!:-) 无论如何,您自己构建了一个管理安全问题的 DLL。在您的代码中,您可以简单地传递一个参数,其中包含通过您的安全 DLL 标识的当前登录用户。

不管怎样,log4net 是我认为的好方法。您可能会将每个用户的事件记录到 SQLite 数据库中,这是个人版的免费数据库。如果我没记错的话,Microsoft Enterprise Library 4.1 - 2008 年 10 月提供了非常有用的工具,而对于程序员来说,需要反复重做的东西很快就会变得乏味。MEL 专门设计用于使这些可重复的例程更容易避免一遍又一遍地重写代码的痛苦。这使您可以专注于对您的客户重要的功能和要求。它是开源的,由微软根据 IBM、HP 和其他类似这样的大公司的需求进行维护。也许有些是我们仍然忽略的存在。无论如何,我认为企业库可能是最好的选择,

如果您习惯于反射,您还可以通过反射来初始化对象的实例,并在保存的同时拥有一个同时记录的例程。

如您所见,有很多方法可以让您轻松实现。这完全取决于您的架构。

好吧,我看到我写了很多。我希望不会让任何人感到厌烦!:-)

祝你今天过得愉快!

于 2009-08-27T12:16:25.577 回答
0

我假设您使用关系数据库作为数据存储。

您当然需要将具有与原始实体几乎相同的表架构的历史表添加到数据库中。

该表中的每一行都有一个指向原始(实时)实体的外键和一个时间戳,因此您现在可以按照什么顺序完成更改。稍后,您可以按 orignialID 从表中检索所有历史信息,按时间戳对其进行排序,然后根据更改创建一些自定义日志消息(考虑反射)。

但是,您必须决定您的更改跟踪应该遍历对象图的“深度”(跟踪关系的更改等)

在每次更新时,将原始行复制到历史表中,引用原始行并添加时间戳,然后再更新原始行。

您可能希望使用存储过程进行更新来封装它。

于 2009-08-27T09:27:55.530 回答
0

您需要多长时间的历史记录?如果答案比应用程序实例长,那么您必须沿着数据库路线走。如果是这种情况,我会在数据库级别处理所有这些,而不是在代码中。也许触发器是你在这里的朋友......

于 2009-08-27T09:31:23.620 回答