views:

314

answers:

1

In my application, I've got a few different types of entities that I have a requirement to do field-level change tracking on. I've googled for this and only can come up with examples on doing simple "Date Inserted" and "Date Updated" audit tracking where you just modify fields on the entity being persisted already. My requirements are more complex because:

  1. I need to create new entities representing the changes not just modify fields on the entity being saved (as with the Date Inserted, Date Updated examples I've found)
  2. I need to save these new entities to the DB in the same transaction updating the tracked entity
  3. I need to track changes to collections of ValueObjects attached to the tracked entity
  4. I don't want to have to write seperate logging code for every tracked entity

Example code:

public interface ITrackChanges {}
{
}

public class Account : ITrackChanges
{
    public int Id;
    public string AccountNumber;
    public string CustomerName;
    public string CustomerAddress;
}

public class Computer : ITrackChanges
{
    public int Id;
    public string AssetTag;
    public string SerialNumber;
    public IEnumerable<IPAddress> IPAddresses;
}

public class IPAddress : ValueObject
{
    public string Address;
}

Whenever any of the values of an Account or Computer object changes or the list of IPAddresses associated with a Computer object changes, I need to create and save these entity change records:

public class EntityChange
{
    public string EntityType;
    public string EntityId;
    public string PropertyName;
    public string OldValue;
    public string NewValue;
}

Each tracked entity implements the ITrackChanges marker interface and each value object inherits from the ValueObject base class. The value objects are mapped as components in NHibernate.

As an example of what I'm looking to get as the end result, if I update the Computer object with Id 1 and change the AssetTag from "ABC123" to "ABC124" and change the list of IP addresses from { "1.2.3.4" } to { "1.2.3.4" , "1.2.3.5" }, I should get 2 EntityChange records:

EntityChange #1
{
    EntityType = "Computer"
    EntityId = 1
    PropertyName = "AssetTag"
    OldValue = "ABC123"
    NewValue = "ABC124"
}

EntityChange #2
{
    EntityType = "Computer"
    EntityId = 1
    PropertyName = "IPAddresses"
    OldValue = "1.2.3.4"
    NewValue = "1.2.3.4, 1.2.3.5"
}

Any ideas on the best way to implement this? From my reading of the docs, it looks like I need to write an interceptor and/or event listener but I haven't been able to find any examples beyond some that just modify the entity being updated. Example code is definitely welcome in any answers.

Am I wrong in assuming that this should be something supported by NHibernate? I was able to implement this in a previous application that used LLBLGen as the ORM but this is the first time I've had to implement this in an application using NHibernate.

+1  A: 

What you want is to use a session Iinterceptor. you can find a sample of using this for Auditing here

Also you will probably get more of a response from the NHibernate mail list.

Aaron Fischer