我正在寻找一种很好的方法来追踪对象所做的每一项更改。
我们正在构建一个自定义框架,我们需要有一个关于谁更改了哪个对象的历史(有点),也可能是什么。
在这种情况下,什么是好的做法?
扩展保存/更新方法以写入“日志”? 我应该尝试使用log4net或一种日志记录扩展吗?
我担心扩展保存/更新/例程的开销。
编辑: 是的,我需要至少查看一个月的变化,客户有时会抱怨数据丢失,他们“忘记”他们删除了它...
Edit2(为了更好地理解,quESTons在评论中提到): 历史记录应存储在db(ms sql)中,我不想在每个类的每个操作中添加日志记录。所有类都继承自我的基类,它提供保存,加载,更新,删除等... 感谢您的进一步回答/评论:)
答案 0 :(得分:3)
这篇文章对你很有意思
http://www.simple-talk.com/sql/database-administration/database-design-a-point-in-time-architecture/
答案 1 :(得分:2)
您基本上在寻找审核解决方案,对吧?我知道Hibernate使用一个名为Hibernate Envers的插件项目来实现它的功能。我能找到的最快的事情是this blog post。至于NHibernate,我相信在将Envers移植到NHibernate方面已经做了很多工作,以便为.NET社区利用这个功能。
我认为在深入研究单独的解决方案之前,找出ETA的内容是值得的。如果你可以将它内置到你的ORM中,这很好,对吧? ; - )
快速查看,我认为Tuna Toksoz正在努力,至少根据他的推文提示。
答案 2 :(得分:0)
我假设您使用关系数据库作为数据存储区。
您肯定需要添加一个历史表,该表的模式与原始实体几乎完全相同。
该表中的每一行都获取原始(实时)实体的外键和时间戳,因此您现在可以按顺序完成更改。稍后,您可以通过表中的orignialID检索所有历史信息,按时间戳排序,然后根据更改创建一些自定义日志消息(考虑反射)。
然而,您必须决定您的更改跟踪应该如何“深入”遍历对象图(跟踪关系变化等)。
在每次更新时,将原始行复制到历史记录表,引用原始行并添加时间戳,然后再更新原始行。
您可能希望使用存储过程进行更新以封装它。
答案 3 :(得分:0)
您需要多长时间的历史记录?如果答案比应用程序实例长,那么您必须沿着数据库路径前进。如果是这种情况,我会在数据库级别处理所有这些,而不是在代码中处理。也许触发器是你的朋友......
答案 4 :(得分:0)
假设您正在使用关系数据库,您可以简单地在Insert,Update和Delete事件上编写触发器,以便在另一个表中写入一个或多个动作。
根据我的说法,使用与记录的原始数据表具有相同定义的历史表的想法也是一个好主意。这允许您将原始表保持为尽可能轻量级,这会将DQL的性能提高到数据库中的表上,并且在将Delete事件跟踪到意外删除的记录时,您无需获取每条记录由用户。
另一种方法,根据每天处理的行数,您可以简单地将字段标记为true或false,无论它是否被删除,并添加一个应该保存当前执行操作的列。假设您将数据库配置为使用Active Directory,以便您可以精确识别当前用户。
在写作的时候,我遇到了另一个想法。你自己也许已经考虑过了! :-)无论如何,你自己构建了一个管理安全问题的DLL。在您的代码中,您可以简单地传递一个参数,其中当前登录的用户已经识别出您的安全DLL。
无论如何,log4net是我认为这样做的好方法。您可能会将每个用户的事件记录到SQLite DB中,该DBite是个人版的免费DB。 Microsoft Enterprise Library 4.1 - 2008年10月,如果我没记错的话,提供非常有用的工具,作为程序员,需要重做和重做的东西一次又一次地变得很无聊。 MEL专门设计用于使这些可重复的例程更容易避免一遍又一遍地重写代码的痛苦。这使您可以专注于对您的客户,功能和要求重要的事情。它是OpenSource,由IBM,惠普和其他类似大公司按照需求由Microsoft维护。也许有些我们仍然忽略了存在。无论如何,我认为企业库可能是最好的方法,总是考虑你的架构,因为它几乎只能通过配置工作。
如果您习惯于反射,您还可以通过反射和保存来初始化对象的实例,同时具有同时记录的例程。
正如您所看到的,有很多方法可以让您无需付出太多努力。这一切都取决于你的架构。
嗯,我看到我写得太多了。我希望不要惹恼任何人! : - )
度过美好的一天!