简体   繁体   English

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

[英]What is the best way to transparently log changes to objects when using LINQ-to-SQL?

I keep track of all changes that are made to objects so that the user can view and rollback to any previous version of any item in the database. 我会跟踪对对象所做的所有更改 ,以便用户可以查看回滚到数据库中任何项目的任何先前版本。

The history database table looks like this: 历史数据库表如下所示:

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

Currently I record these changes whenever the user fills out a form so I have complete information of the old and new state of the object. 目前,只要用户填写表单 ,我就会记录这些更改,因此我可以获得有关对象的旧状态和新状态的完整信息。

However, now I need to make this historical data logging available from code . 但是,现在我需要从代码中获取此历史数据日志记录。 It needs to work transparently when LINQ-to-SQL is used, ie the developer should not have to do any extra work, ie the following code should cause a write to the history table as well: 当使用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();

I can imagine I can accomplish this in two ways: 我可以想象我可以通过两种方式实现这一目标:

  1. override db.SubmitChanges() but then the question is how do I get access to the objects which are awaiting changes. 覆盖db.SubmitChanges(),但问题是如何访问等待更改的对象。
  2. attach my logging method to an OnSubmitChanges event but I haven't been able to find a solution to this yet 将我的日志记录方法附加到OnSubmitChanges事件,但我还没有找到解决方案

Has anyone ever worked on this problem or know of a good approach to solve it? 有没有人曾经解决过这个问题,或者知道一个好方法来解决它?

I've done some similar work on auditing changes -- which is the first step. 我在审计变更方面做了类似的工作 - 这是第一步。 My solution works by making my designer context abstract then deriving the real context from it and overriding SubmitChanges. 我的解决方案通过使我的设计器上下文抽象然后从中导出真实上下文并重写SubmitChanges来工作。 It works in conjunction with a separate audit context and a helper class that can take an object and construct the audit object from it. 它与一个单独的审计上下文和一个辅助类一起工作,该类可以获取一个对象并从中构造审计对象。 It relies on attributes to give the necessary information on which class is the audit class for a particular object. 它依赖于属性来提供有关哪个类是特定对象的审计类的必要信息。

You can find more information on my blog at http://farm-fresh-code.blogspot.com . 您可以在我的博客上找到更多信息, 网址http://farm-fresh-code.blogspot.com It's too involved to repeat here. 在这里重复过于复杂。

For your first question, you can get access to the objects awaiting changes with db.GetChangeSet() and to know which fields changed and what was the original value, you can use: 对于第一个问题,您可以访问等待使用db.GetChangeSet()更改的对象,并了解哪些字段已更改以及原始值是什么,您可以使用:

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

Since L2S generates code for you, and you wish to alter the behaviour of the generated code I see two possibilities: 由于L2S为您生成代码,并且您希望改变生成的代码的行为,我看到两种可能性:

  1. You start using T4 templates to generate the code from the dbml file and alter the template to add your functionality. 您开始使用T4模板从dbml文件生成代码并更改模板以添加您的功能。 This method is described here 这里描述这种方法
  2. You add the functionality to the generated (partial) datacontext class by writing a partial class yourself. 您可以通过自己编写部分类来将功能添加到生成的(部分)datacontext类中。 In your partial class you can implement the create/update/delete methods (CreateCustomer, UpdateCustomer and DeleteCustomer) adding the functionality to store the change. 在您的分部类中,您可以实现创建/更新/删除方法(CreateCustomer,UpdateCustomer和DeleteCustomer),添加存储更改的功能。

I hope these pointers can help you on your way. 我希望这些指针可以帮助你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM