Click here to Skip to main content
15,885,078 members
Articles / Web Development / ASP.NET

Implementing audit / history tracking using the Prototype pattern

Rate me:
Please Sign up or sign in to vote.
4.47/5 (9 votes)
17 Mar 2009CPOL7 min read 81.4K   147   54   7
How to implement audit / history tracking using the Prototype pattern.

Table of contents

Introduction and goal

Data audit trail is one of the most required features in any project. This article will talk about audit trail through application using the Prototype pattern. Most projects have a three tier architecture and have the core business objects in place. In this article, we will see how we can leverage existing 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. In this article, we will only look at business object audit trailing.

Currently I am circulating my free .NET eBook. I have collected around 500 FAQ questionnaire, hope you enjoy it… http://www.questpond.com/SampleDotNetInterviewQuestionBook.zip.

Screenshot of what we are targeting

Image 1

Approaches of implementing an audit trail

An audit trail in a project can be implemented in two basic ways:

  • First is through the application
  • Second is using database functionalities like triggers or Stored Procedures

This article will concentrate on the first approach, i.e., through the application. We will use the Prototype pattern to create a clone of the old values and then do auditing.

The customer and supplier projects

For our auditing project, we will take up a sample project which has customer and supplier data. There are two tables and we need to maintain one as the customer table and the other as the supplier.

Supplier Table
Sup_code This is a simple supplier code which is unique to each 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.

Implementing the three tier architecture

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 three tier architecture. Below is the three tier view of the customer component. We have the UI ASPX pages which are 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 the supplier. For simplicity sake, we are not showing the supplier class here.

Image 2

Visualizing the methodology for the audit trail

When talking about data auditing, we will need two things: old values and new values.

Image 3

The class is a data container and the properties of the class hold the current, recent, and changed values. In other words, the ‘new value’ is contained in the private properties of the class. Now remains the issue of 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.

Image 4

So how do we create a copy of the customer object?

The GetCustomerData method is the place where we load the current object and this is also the place where we need to create the copy of the object. We will be using the Prototype pattern to create the clone of the customer object. In the next sections, we will just run through the basics of the Prototype pattern and then implement the audit trail functionality.

Understanding the Prototype pattern

The Prototype pattern falls in the section of Creational patterns. It gives us a way to create new objects from existing instances of an 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 that by just setting objects we can get a clone, then you are mistaken. By setting an object to another object, we set the reference of the object ByRef. So changing the new object also changes the original object. To understand the ByRef fundamentals more clearly, consider the figure below. Following is the sequence of the code:

  • In the first step, we create the first object, i.e., obj1 from class1.
  • In the second step, we create 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 obj1 to obj2.
  • In the fifth step, we change the obj2 value.
  • Now we display both the values and we find that both the objects have the new value.

Image 5

The conclusion of the above example is that objects when set to other objects are set ByRef. So changing new object values changes the old object values as well.

There are many instances when we want that the new copy object changes not affect the old object. The answer to this is the Prototype pattern.

Let us look at how we can achieve this using C#. In the figure below, we have the customer class ClsCustomer which needs to be cloned. This can be achieved in C# by using the MemberWiseClone method. In Java, we have the Clone method to achieve this. 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 completely cloned copy.

Image 6

Shallow and deep cloning

There are two types of cloning for Prototype patterns. One is shallow cloning which you have just seen in the first question. In shallow copy, only that object is cloned, any objects contained 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 add 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 deep cloning, and when only the parent is cloned, it is termed as shallow cloning.

Image 7

Implementing the cloning feature in the customer class

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. The code snippet below shows how we have used memberwiseclone to create a by value decoupled object inside the customer class.

Image 8

The audit table design

I am sure as per project needs, 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 defines 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 newly changed values

The audit class, the plumbing block

When talking about object oriented programming, every class should do its job. So the customer class should do validation related to its properties while the supplier should do validations related to the supplier table. The audit functionality is neither the job of the supplier nor the job of the 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 adds it 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 a simple if condition to achieve our task.

Image 9

Calling the audit class in the customer

So now we are finally at the end of the movie. We just consume the audit object in the customer class and do auditing.

C#
public void Update(clsCustomer objCustomer, int CustomerId)
{
    objcustomerClone = (clsCustomer)this.getClone();
    objcustomerClone.getCustomerData(CustomerId);
    objAudit.AuditCustomer(objCustomer, objcustomerClone);
    objDataLayer.UpdateCustomerDB(Name, Address, CustomerId);
}

Below is a nice Design Pattern youtube video which explains step by step how to use Design pattern in C# projects.

Image 10

Source code

The source code has audit trailing for both the customer and supplier tables.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect https://www.questpond.com
India India

Comments and Discussions

 
GeneralMy vote of 5 Pin
Himanshu Thawait17-Sep-10 4:07
Himanshu Thawait17-Sep-10 4:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.