Question

Most of the examples I've seen online shows object change tracking in a WinForms/WPF context. Or if it's on the web, connected objects are used, therefore, the changes made to each object can be tracked.

In my scenario, the objects are disconnected once they leave the data layer (Mapped into business objects in WCF, and mapped into DTO on the MVC application)

When the users make changes to the object on MVC (e.g., changing 1 field property), how do I send that change from the View, all the way down to the DB?

I would like to have an audit table, that saves the changes made to a particular object. What I would like to save is the before & after values of an object only for the properties that we modified

I can think of a few ways to do this

1) Implement an IsDirty flag for each property for all Models in the MVC layer(or in the javascript?). Propagate that information all the way back down to the service layer, and finally the data layer.

2) Having this change tracking mechanism within the service layer would be great, but how would I then keep track of the "original" values after the modified values have been passed back from MVC?

3) Database triggers? But I'm not sure how to get started. Is this even possible?

Are there any known object change tracking implementations out there for an n-tier mvc-wcf solution?

Example of the audit table:

Audit table

Id              Object         Property         OldValue                NewValue
--------------------------------------------------------------------------------------
1               Customer       Name             Bob                     Joe
2               Customer       Age              21                      22
Was it helpful?

Solution

Possible solutions to this problem will depend in large part on what changes you allow in the database while the user is editing the data.

In otherwords, once it "leaves" the database, is it locked exclusively for the user or can other users or processes update it in the meantime?

For example, if the user can get the data and sit on it for a couple of hours or days, but the database continues to allow updates to the data, then you really want to track the changes the user has made to the version currently in the database, not the changes that the user made to the data they are viewing.

The way that we handle this scenario is to start a transaction, read the entire existing object, and then use reflection to compare the old and new values, logging the changes into an audit log. This gets a little complex when dealing with nested records, but is well worth the time spent to implement.

If, on the other hand, no other users or processes are allowed to alter the data, then you have a couple of different options that vary in complexity, data storage, and impact to existing data structures.

For example, you could modify each property in each of your classes to record when it has changed and keep a running tally of these changes in the class (obviously a base class implementation helps substantially here).

However, depending on the point at which you capture the user's changes (every time they update the field in the form, for example), this could generate a substantial amount of non-useful log information because you probably only want to know what changed from the database perspective, not from the UI perspective.

You could also deep clone the object and pass that around the layers. Then, when it is time to determine what has changed, you can again use reflection. However, depending on the size of your business objects, this approach can impose a hefty performance penalty since a complete copy has to be moved over the wire and retained with the original record.

You could also implement the same approach as the "updates allowed while editing" approach. This, in my mind, is the cleanest solution because the original data doesn't have to travel with the edited data, there is no possibility of tampering with the original data and it supports numerous clients without having to support the change tracking in the UI level.

OTHER TIPS

There are two parts to your question:

  1. How to do it in MVC:

The usual way: you send the changes back to the server, a controller handles them, etc. etc.. The is nothing unusual in your use case that mandates a change in the way MVC usually works. It is better for your use case scenario for the changes to be encoded as individual change operations, not as a modified object were you need to use reflection to find out what changes if any the user made.

  1. How to do it on the database: This is probably your intended question:

First of all stay away from ORM frameworks, life is too complex as it.

On the last step of the save operation you should have the following information:

  • The objects and fields that need to change and their new values.

You need to keep track of the following information:

  • What the last change to the object you intend to modify in the database.

This can be obtained from the Audit table and needs to be saved in a Session (or Session like object).

Then you need to do the following in a transaction:

  • Obtain the last change to the object(s) being modified from the database.
  • If the objects have changed abort, and inform the user of the collision.
  • If not obtain the current values of the fields being changed.
  • Save the new values.
  • Update the Audit table.

I would use a stored procedure for this to make the process less chatty, and for greater separations of concerns between the database code and the application code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top