使用LINQ-to-SQL时,透明地记录对象更改的最佳方法是什么?

时间:2009-12-16 13:20:45

标签: c# linq linq-to-sql change-tracking

我会跟踪对对象所做的所有更改,以便用户可以查看回滚到任何项目的任何先前版本在数据库中。

历史数据库表如下所示:

Item     | ItemId | Field     | WhenChanged         | OldValue | NewValue
customer | 6      | LastName  | 2009-12-31 13:00:04 | Sanders  | Sanders-Smith
customer | 5      | FirstName | 2009-12-31 12:11:14 | Jym      | Jim

目前,只要用户填写表单,我就会记录这些更改,因此我可以获得有关该对象的旧状态和新状态的完整信息。

但是,现在我需要从代码中提供此历史数据记录。当使用 LINQ-to-SQL 时,它需要工作透明,即开发人员不应该做任何额外的工作,即以下代码应该导致写入历史表也是:

using (var db = Datasource.GetContext())
{
    var customers = from c in db.Customers
        where c.Status == "waiting"
        select c;
    foreach(var customer in customers)
    {
        customer.Status = "finished";
    }
}
db.SubmitChanges();

我可以想象我可以用两种方式实现这一目标:

  1. 覆盖db.SubmitChanges()但问题是如何访问等待更改的对象。
  2. 将我的日志记录方法附加到 OnSubmitChanges 事件,但我还未能找到解决方案
  3. 有没有人曾经解决过这个问题或知道解决问题的好方法?

3 个答案:

答案 0 :(得分:2)

我已经对审核更改做了一些similar work - 这是第一步。我的解决方案通过使我的设计器上下文抽象然后从中导出真实上下文并重写SubmitChanges来工作。它与一个单独的审计上下文和一个辅助类一起工作,该类可以获取一个对象并从中构造审计对象。它依赖于属性来提供关于哪个类是特定对象的审计类的必要信息。

您可以在我http://farm-fresh-code.blogspot.com的博客上找到更多相关信息。在这里重复过于复杂。

答案 1 :(得分:2)

对于您的第一个问题,您可以访问等待db.GetChangeSet()更改的对象,并了解哪些字段已更改以及原始值是什么,您可以使用:

ITable table = db.GetTable(entity.GetType());
ModifiedMemberInfo[] modifiedMembers = table.GetModifiedMembers(entity);
object original = table.GetOriginalEntityState(entity);

答案 2 :(得分:1)

由于L2S为您生成代码,并且您希望改变生成代码的行为,我看到两种可能性:

  1. 您开始使用T4模板从dbml文件生成代码并更改模板以添加您的功能。该方法描述为here
  2. 您可以通过自己编写部分类来将功能添加到生成的(部分)datacontext类中。在您的部分类中,您可以实现创建/更新/删除方法(CreateCustomer,UpdateCustomer和DeleteCustomer),添加存储更改的功能。
  3. 我希望这些指示可以帮助你。