Introduction
As an experienced developer one may not be able to answer the question "How many times I wrote database centric code to save/retrieve/delete business entities?" We wrote database centric code many times in our lives. Sometimes by getting tired, we thought to get rid of writing such common code again and again!
Most of the business application requires us to write database centric code like the following:
OleDbConnection connection = null;
try
{
string strSql = "SELECT ID, Name, ... FROM tblCust;";
connection =
OleDbCommand command = new OleDbCommand(strSql, connection);
command.Parameters.Add("@ID", 1323);
.
.
command.Parameters.Add("@Address", "First Lane");
OleDbDataReader reader = command.ExecuteReader();
if (reader.Read())
{
}
} catch
{
}
After getting bored on writing such same logic to persist business entities, engineers and researchers started thinking a way to reduce application code to persist business entities. Writing logic for Creating, Retrieving, Updating, and Deleting business objects to and from the database tables looks like a common pattern in any given language. That is, the code to do such operation looks almost similar in all context. If you wish to perform an INSERT operation into a database table to persist a business object, there are many chances that you write the same code logic to persist other business entities in a brand new application.
When such patterns are seen over and over again, researchers are thinking to establish a framework to achieve the same goal by providing an API. We have seen such frameworks to persist business entities. NHibernate is an example, using which we can minimize database centric code, which in turn, also makes our lives easier.
Background
In 2003, I started developing a Human Resource Management System (HRMS) called HRMZone using J2EE, part of which offers posting of visitors' resume. The application is similar to those of job searching websites such as http://www.jobpilot.com/. While I was tired of coding same database code, I started thinking to develop a Framework to minimize the same efforts; as the code to persist business entities to a backend server looks like a common pattern. Motivation of developing the framework came from my knowledge on the Java's reflection API.
By spending a whole day, I was able to write my first Object Persistence Framework in Java; I named it AutoPersist Framework initially. Interestingly, it saved my live more than I though it could. Sadly, I saw after a couple of months that there is a stable persisting framework had been released called 'Hibernate'! Seemed that I reinvented the same wheel!! Yes, although it was the same wheel, it has the different shape than Hibernate in one aspect; AutoPersist didn't (and still doesn't) require someone to write an OR Mapping file (a schemaic XML mapping).
After Visual C# had been released, I though that I would write a port of my AutoPersist
in C# language. I was tremendously busy those days and could not implement a port of the same. Finally, in this week, I have had a little leisure at my home and have written the port of AutoPersist
in C# - the very first version that only supports basic CRUD without supporting any complex or simple relational integrity. That is, the first version of AutoPersist
will neither allow saving nested object
nor it will allow master-child relationship of Database Entities. But interestingly, it can save any business object without writing a mapping file (a schematic mapping in the form of XML).
Using the code
The actual source of the AutoPersist API can be found in the source download link of this article; on the other hand the demo download consist the demo of the same project.
Consider that we have a class called Customer
, which defines two properties: Name
and Address
:
public class Customer
{
private int id;
private string name;
private string address;
public Customer()
{
}
public int ID
{
set { this.id = value; }
get { return this.id; }
}
public string Name
{
set { this.name = value; }
get { return this.name; }
}
public string Address
{
set { this.address = value; }
get { return this.address; }
}
}
Now our goal is to persist an object
of type Customer
without writing database centric code! We will use PersistManager
, which is the central heart of the AutoPersist API to achieve this. To have an instance of this class, we need to invoke its NewInstance()
method which takes a parameter of type DBInfo
to determine the backend type, connection string etc. Until recently, the DBInfo
just only provides the connection string property. So the following code snippet at the client end will return an instance of PersistManager
:
DBInfo info = new DBInfo();
info.ConnectionString =
PersistManager objPersistManager = PersistManager.NewInstance(info);
After having an instance of PersistManager
class, we can save our Customer
in the following way:
Customer objCustomer = new Customer();
objPersistManager.CreateObject(objCustomer);
Convention
To save a business object using the AutoPersist API, one doesn't need to write any schematic mapping file. So how will the API determine the name of the database table into which a row will be created or deleted? And how will the API determine the name of the columns to map to the property names of an object?
To achieve the goal of automatic persistency for our business object, we must follow some conventions:
Your business entity (your class) must follow the following structure:
public class Customer
{
private int id;
public Customer()
{
}
public int ID
{
set { this.id = value; }
get { return this.id; }
}
}
In the database table:
- there must be a table, name of which must match the name of the object, i.e., table name =
object.GetType().Name
, where object is your object. For the above example, the table name must be 'Customer'
- there must be a auto-increment column called 'ID' (autonumber in MS Access).
- there must be columns, name of which must match with all the property names of the object. For example, if there is property named
CustomerName
, in the table, there must be a column exactly called 'CustomerName'.
In the demo project, there is a MS Access database called 'AutoPersist' in the '/database' folder to show an example of persisting Customer entity.
Testing
In the first version of the AutoPersist API only property of types 'int'
and 'string'
have been tested with only MS Access database. For accessing database, I have only used OLE DB API of the .NET Framework.
Enhancement
One may enhance the Framework's code to suite one's own need by supporting (some or all of) the following:
- saving nested object
- maintaining a relational integrity
- both automatic and mixed-mode persistency with the aid of a schematic mapping file (usually an XML file)
- other database server/application
- other database access API such as ADO.NET
- code emitter for creating ASP.NET's web forms (along with code behind and helper classes) or WinForm for Desktop Application
All the above can be achieved. If you have any question or require any support, just drop me an email.
Performance
Balancing a program in all aspect is almost impossible. One needs to compromise an aspect to achieve other advantages. If we use Automatic Persistency, which heavily depends of utilizing Reflection API, we must compromise the speed of the Application. Reflection requires introspection of object structure at runtime (as opposed to design time) to find out method/properties to be invoked. This is somewhat similar to late binding feature in COM, which costs a performance bottleneck.
Final Thoughts
Obviously nothing can stop us from getting advantages of using the AutoPersist like API. There must be solutions for each and every problem. Achieving a performance benefit is hard but not impossible! Are you confused? If you are, please drop me emails stating your confusion -:)