views:

411

answers:

5

I am looking for a good way to track down every change that is made on an object.

We are building a custom framework and we need to have a history (kind of) about who changed which object when and maybe also what.

What is a good practice in this case?

Extend the save / update methods to write a "log"? Should I try with log4net or kind of logging extensions?

I'm concerned about the overhead on extending the save / update / routines.

Edit: Yes I need to see the changes at least for a month, customers sometimes complain about lost data and they "forget" that they deleted it...

Edit2 (for better understanding, questons asked in comments): The history should be stored in db (ms sql) and I don't like to add the logging in every action for every class. All classes ar inherited from my baseclass which provides save, load, update, delete etc... Thanks for further answers / comments :)

A: 

I assume you are using a relational db as datastore.

you will certainly need to add a history table with nearly identical table schema as for the original entities to the database.

Each row in that table gets a foreign key to the original(live) entity, and a timestamp, so you now in which order the change was done. Later on, you can retrieve all the history information by orignialID from the table, sort it by timestamp and then create some custom log message based on the changes (consider reflection).

You will however have to decide how "deep" your change tracking should traverse the object graph (tracking changes on relations etc.)

On every update you copy the original row to the histor table, reference the original row and add a timestamp, before you update the original row.

You may want to use a stored procedure for updates to encapsulate this.

Johannes Rudolph
yes I use a relational db(sql server 2005 for now). Tracking the relations will also be needed (e.g. product description added to x from user y).
griti
A: 

How long do you need the history for? If the answer is longer than the application instance then you have to go down the database route. If that's the case, I'd handle all of it at the db level, not in the code. Perhaps triggers are your friend here...

grenade
good point, I will check further about the usability for restoring a history entry and stuff. On database level I still need to create the history-stuff for all objects, sometimes 3 or more tables per object... uff <:
griti
as far as I checked the customer needs, the history should be done in application level together with nHibernate. With triggers and nHibernate it would be a solution, but not in my case.
griti
+1  A: 

this article may be interesting for you

http://www.simple-talk.com/sql/database-administration/database-design-a-point-in-time-architecture/

marc.d
very interesting article, will read trough it ;)
griti
A: 

Assuming that your are using a relational database, you could simply code triggers on Insert, Update and Delete events to write an action or so within another table.

The idea of using a history table with the same definition as the original data table logged is also a good idea, according to me. This allows you to keep your original table as lightweight as possible, this increases the performance of DQL onto your table within the database, and you do not need to fetch every records when it comes to trace a Delete event onto a record that was accidently deleted by a user.

Another way, depending on the number of rows treated everyday, you may simply flag a field true or false whether it is deleted, and add a column that should save the current doing the action. Assuming that you configured the DB to work with Active Directory, so that you may identify with precision the current user.

While writing, I came accross another idea. You perhaps already thought about it yourself! :-) Anyway, you build yourself a DLL managing security matters. Within your code, you could simply pass a parameter with the currently logged user identified throguh your security DLL.

Whatsoever, log4net is I think a good way of doing it. You might perhaps log the events for every user into a SQLite DB which is a free DB for the personal edition. Microsoft Enterprise Library 4.1 - October 2008, if I remember correctly, offers such tools that are very useful and, as programmers, stuff that need to be redone and redone again and again become rapidly boring. MEL is designed especially to make these repeatable routines easier to avoid the pain of rewriting code over and over again. This allows you to concentrate upon what's important for your client, the features and requirements. It is OpenSource and maintained by Microsoft as per demand by such companies as IBM, HP and others big companies like these. Maybe some that we still ignore the existence. In anyway, I think Enterprise Library might be the best way to go, always considering your architecture, as it works almost by configuration only.

If you're used to reflection, you could also initialize an instance of your objects through reflection and while saving, having a routine which logs at the same time.

As you can see, there are many ways to make it possible to you without much efforts. It all depends on your architecture.

Well, I see I've written much. I hope not to bore anyone! :-)

Have a nice day!

Will Marcouiller
Triggers are one way to do it, but then I would also need to map all in nhibernate in order to load it (the "right" way). Of course it will be more flexible with reflections, so I will think about the whole tracking/logging and for sure check what the customer wants / pays ;)
griti
also I would like to have the logging/triggerin on application level, forgot to mention on my comment :-)
griti
I know of Enterprise Library Logging features. Mainly, Enterprise Library requires solely configuration to work properly. I guess this might be an interesting way to explore.
Will Marcouiller
+1  A: 

Your basically looking for an auditing solution, right? I know Hibernate has functionality for it using an addon project called Hibernate Envers. This quickest thing I could find on this is this blog post. As for NHibernate, I believe there's work being done on porting Envers to NHibernate, to leverage this functionality for the .NET community as well.

I think it would be worth it to find out what the ETA on that is, before diving into a separate solution. If you can get it built into your ORM that's nice, right? ;-)

Just checked quickly, I think Tuna Toksoz is working on it, at least according to his twitter feed.

Erik van Brakel
As I got deeper into my problem, audit log seems what I need, yes.Envers sounds really nice, also the flexibility looks perfect. But I could not find any serious information about a .Net port, Tuna Toksoz has no blog post about it... I read also ( http://nhforge.org/wikis/howtonh/creating-an-audit-log-using-nhibernate-events.aspx ) which looks like a possible way to do it by myself.
griti