Data audit trail is one of the most required features in any project. This article will talk about audit trail through application using prototype pattern. Most the projects have three tier architecture and have the core business objects in place. In this article we will see how we can leverage the current business objects to implement auditing functionalities.
Implementing Audit/history tracking using Prototype Pattern
Introduction and Goal
Screen shot of what we are targeting
Approaches of implementing Audit trail.
The customer and supplier project
Implementing the three tier architecture
Visualizing the methodology for Audit trail
So how do we create a copy of the customer object?
Understanding the prototype pattern
Shallow and Deep cloning
Implementing the cloning feature in customer class
The Audit table design
The Audit class, the plumbing block
Calling the Audit class in the customer
Source Code
Data audit trail is one of the most required features in any project. This article will talk about audit trail through application using prototype pattern. Most the projects have three tier architecture and have the core business objects in place. In this article we will see how we can leverage the current business objects to implement auditing functionalities.
I am not saying that this is the best way. There are many other ways like dataset, triggers etc. This article we will only limit to business object audit trailing.
Now days I am circulating my free DotNet Ebook. I have collected around 500 FAQ questionnaire hope you enjoy it…
http://www.questpond.com/SampleDotNetInterviewQuestionBook.zip

Audit trail in project can be implemented by two basic ways:-
- First is through the application
- Second is using database functionalities like trigger or stored procedures.
This article will concentrate in the first approach i.e. through the application. We will use prototype pattern to create a clone of the old values and then do auditing.
For our auditing project we will take up a sample project which has customer and supplier data. Their are two tables we need to maintain one is the customer table and the other the supplier.
Supplier Table |
Sup_code |
This is a simple supplier code which is unique to each of the supplier. |
Sup_telephone |
This contains the telephone |
Customer table |
Name |
This attribute defines the name for the customer. |
Address |
This property holds the address of the customer. |
We will first create a simple three tier architecture which will do our insert update delete. We will then build our audit trail feature using the 3 tier architecture. So below is the three tier view of the customer component. So we have the UI ASPX pages which is consuming the customer component and the customer component in turn calls the database for insert, update and delete operations. In the same manner we will implement for supplier. For simplicity sake we are not showing the supplier class here.

When talk about data auditing we will need two things old values and new values.

The class is a data container and the properties of the class hold the current, recent and changed values. So in other words the ‘new value’ is contained in the private properties of the class. Now remains the issue where we should maintain the old values.
So the approach for this is we will create the object of the class within itself. This object will hold the old value snapshot.

The ‘GetCustomerData method is the place where we load the current object and this place also forms the place where we need to create the copy of the object. We will be using prototype pattern to create the clone of the customer object. In the next sections we will just run through the basics of prototype pattern and then implement audit trail functionality.
Prototype pattern falls in the section of creational pattern. It gives us a way to create new objects from the existing instance of the object. In one sentence we clone the existing object with its data. By cloning any changes to the cloned object does not affect the original object value. If you are thinking by just setting objects we can get a clone then you have mistaken it. By setting one object to other object we set the reference of object BYREF. So changing the new object also changed the original object. To understand the BYREF fundamental more clearly consider the figure ‘BYREF’ below. Following is the sequence of the below code:-
- In the first step we have created the first object i.e. obj1 from class1.
- In the second step we have created the second object i.e. obj2 from class1.
- In the third step we set the values of the old object i.e. obj1 to ‘old value’.
- In the fourth step we set the obj1 to obj2.
- In the fifth step we change the obj2 value.
- Now we display both the values and we have found that both the objects have the new value.

The conclusion of the above example is that objects when set to other objects are set BYREF. So changing new object values also changes the old object value.
There are many instances when we want the new copy object changes should not affect the old object. The answer to this is prototype patterns.
Let us look how we can achieve the same using C#. In the below figure ‘Prototype in action’ we have the customer class ‘ClsCustomer’ which needs to be cloned. This can be achieved in C# my using the ‘MemberWiseClone’ method. In JAVA we have the ‘Clone’ method to achieve the same. In the same code we have also shown the client code. We have created two objects of the customer class ‘obj1’ and ‘obj2’. Any changes to ‘obj2’ will not affect ‘obj1’ as it’s a complete cloned copy.

There are two types of cloning for prototype patterns. One is the shallow cloning which you have just read in the first question. In shallow copy only that object is cloned, any objects containing in that object is not cloned. For instance consider the figure ‘Deep cloning in action’ we have a customer class and we have an address class aggregated inside the customer class. ‘MemberWiseClone’ will only clone the customer class ‘ClsCustomer’ but not the ‘ClsAddress’ class. So we added the ‘MemberWiseClone’ function in the address class also. Now when we call the ‘getClone’ function we call the parent cloning function and also the child cloning function, which leads to cloning of the complete object. When the parent objects are cloned with their containing objects it’s called as deep cloning and when only the parent is clones its termed as shallow cloning.

As said before the ‘getCustomerData’ function loads the values in the class. As soon as the class loads its own value we will load a clone of the value in the cloned object inside the same class. Below code snippet shows how we have used “memberwiseclone” to \create a by value decoupled object inside the customer class.

I am sure as per project need the audit table design can be very complicated. But for our simplicity purpose we will have the audit table as shown below.
Audit table design |
Id |
A simple identifier which defined a unique key |
Old value |
This will hold the field name + the old values for the field name |
New Value |
This will hold the field name + the new changed values |
When talk about object oriented programming every class should do his job. So the customer class should do validation related to his properties while supplier should do validations related to supplier table. The audit functionality is neither the job of supplier nor the job of customer. It’s a technical functionality in other words it’s a plumbing block.
So we have created a ‘clsAudit’ class which will take in the current customer object as well as the cloned object and then add the same to the audit table we discussed in the previous section.
We can improve this functionality and make it more generic by using reflection. For simplicity sake we have currently used simple if condition to achieve our task.

So now we are finally to the end of the movie. We just consume the audit object in the customer class and do auditing.
public void Update(clsCustomer objCustomer, int CustomerId)
{
objcustomerClone = (clsCustomer)this.getClone();
objcustomerClone.getCustomerData(CustomerId);
objAudit.AuditCustomer(objCustomer, objcustomerClone);
objDataLayer.UpdateCustomerDB(Name, Address, CustomerId);
}
At the top this article you can find the source code. It has audit trailing for both customer and supplier tables.