TokenRobotz – An ORM Experiment

In this article I am revealing the inner workings of an Object Relational Mapping framework (Download) which I created years back. In the year 2005 I was introduced to Hibernate (ORM for Java) and NHibernate (ORM for .Net) by our Tech Lead. I found the following advantages in it:

  • Object Oriented Wrapping over Database Operations
  • No CRUD code generation Multiple Data Provider Support
  • Reduction in Development time

In 2006 when I was offered a Tech Lead job, I introduced the same to another team the core developer found it difficult to learn NHibernate. The core reason was the XML files associated. They preferred the DataSet and DataReader way and resisted change. Inorder to get the developer confidence and maintain the Object Oriented Rhythm in coding I decided to create an ORM which would be pure C#, Free from XML mapping still maintaining the leverage of CRUD code dynamic generation, Dealing Tables as Entities, Multiple Data provider support and mainly Ease of Use.

Day and Night coding of 2 weeks I was able to create an ORM which was re-factored later. It is not such great as Entity Framework but the Team given an overwhelming response to this new piece of code and they passionately adapted it. Most of them where happy with ORM for the first time and amazed by the reduced code. After a few months I can hear that some developers denied of taking a project without using this framework. They argued it will take much development time without ORM. Thanks to all my dear friends who encouraged me to make this a great success. After all it is a Tool of Old Times and I switched to Linq-To-Sql and Entity Framework for the newer projects.

I would like to share the same ORM framework here. Learning the underlying classes will surely increase our language abilities through Reflection, Design Patterns inside ADO.NET, Layering etc. The project is named as TokenRobotz.

Supported Features

Following are the features supported by this ORM:

  • CRUD abstracted to Base class
  • Database Session for sharing Connection
  • Search Operations involving AND/OR Conditions supported
  • Layered Architecture enabling easier Data Layer Replacement
  • Lazy Loading through Foreign Keys
  • SQL Server, Oracle, MS Access, ODBC Supported
  • SQL Server Tables and Views Supported
  • Default Sort Property Enabling
  • Code Emitter for Entity Creation
  • Code Emitter for EntityDA Creation

Limitations

Following are the limitations of this ORM:

  • No IDE Designer Support
  • No LINQ Provider Support
  • No Caching of Objects

Modules

Following are the modules involved:

TokenRobotz The core ORM framework assembly
Emitter Windows Application to generate the entity code from database table
Demo WinForms Demo application involving CRUD, Search operations etc.
Freemen.Empire A utility assembly which is referenced by TokenRobotz

The core classes and other important files are explained below.

BaseDA

From the folder TokenRobotzCore you will find the generic class named BaseDA. It works as the base for all the Insert, Update, Delete, Find, FindAll methods. The SQL is generated from this class.

clip_image002

clip_image004

Following is the INSERT SQL Code generation code. You can see the Reflection class PropertyInfo used inside it.

public string GetInsertSql(System.Type type)

{

StringBuilder builder = new StringBuilder();

DAUtils utils = new DAUtils(null);

builder.Append(“INSERT INTO “);

builder.Append(utils.GetTableName(type));

builder.Append(“(“);

// Create a copy of the PropertyInfos

IList<PropertyInfo> PIList = new List<PropertyInfo>();

foreach (PropertyInfo pInfo in type.GetProperties())

PIList.Add(pInfo);

foreach (PropertyInfo pInfo in PIList)

{

string FieldName = utils.GetFieldName(pInfo);

if (FieldName != String.Empty && FieldName != InfoProvider.GetPrimaryKeyFieldName()

&& CanIncludeInInsert(pInfo))

{

utils.CheckFieldName(FieldName);

builder.Append(FieldName);

builder.Append(“,”);

}

}

builder.Remove(builder.Length – 1, 1);

builder.Append(“)”);

builder.Append(” VALUES “);

builder.Append(“(“);

foreach (PropertyInfo pInfo in PIList)

{

string FieldName = utils.GetFieldName(pInfo);

if (FieldName != String.Empty && FieldName != InfoProvider.GetPrimaryKeyFieldName()

&& CanIncludeInInsert(pInfo))

{

builder.Append(this.InfoProvider.GetSession().Options.ParameterSymbol);

builder.Append(FieldName);

builder.Append(“,”);

}

}

builder.Remove(builder.Length – 1, 1);

builder.Append(“)”);

return builder.ToString();

}

Filter

The class Filter acts as the base for all Filter sub classes like AndFilter, OrFilter, EqualsFilter etc.

clip_image006

The condition specified in the filter will be converted to the equivalent SQL. We can combine OR and AND operations using the AndFilter, OrFilter classes respectively.

TokenRobotzSession

TokenRobotzSession is the context class which acts as a shareable object between different database calls. It could be related to ADO.NET Entity Framework Context.

Following is the code snap of it:

clip_image008

BaseEntity

BaseEntity acts as the base class for all entities. It performs the Serializable attribute and holds the session as property.

All the entities are derived from this class. The Code Emitter Utility takes care of assigning the base class to BaseEntity.

clip_image010

TypeMap.xml

The TypeMap.xml can be used to dynamically add Database Data Types which are not listed in the xml file.

<?xml version=”1.0″ encoding=”utf-8″ ?>

<TypeMap>

<DbType DbTypeName=”130″ CSharpTypeName=”string”></DbType>

<DbType DbTypeName=”17″ CSharpTypeName=”byte”></DbType>

<DbType DbTypeName=”2″ CSharpTypeName=”int”></DbType>

<DbType DbTypeName=”3″ CSharpTypeName=”int”> <!– is long… for specific purpose treated as int–></DbType>

<DbType DbTypeName=”11″ CSharpTypeName=”bool”></DbType>

<DbType DbTypeName=”5″ CSharpTypeName=”double”></DbType>

<DbType DbTypeName=”6″ CSharpTypeName=”double”></DbType>

<DbType DbTypeName=”128″ CSharpTypeName=”Byte[]”></DbType>

<DbType DbTypeName=”7″ CSharpTypeName=”DateTime”></DbType>

<DbType DbTypeName=”4″ CSharpTypeName=”float”></DbType>

<DbType DbTypeName=”131″ CSharpTypeName=”int”></DbType> <!–sqlserver numeric (18, 0)–>

<DbType DbTypeName=”129″ CSharpTypeName=”string”></DbType> <!–sqlserver text–>

<DbType DbTypeName=”135″ CSharpTypeName=”DateTime”></DbType> <!–sqlserver datetime–>

</TypeMap>

Factory Method

The DbProviderFactoryof ADO.NET is implementing Factory Method Design Pattern. It helps us in attaining the flexibility to support different Data Providers like SQL Server, Oracle etc. by instantiating the right Connection and Command Classes.

clip_image012

Source Code

All the source code and demo application can be found here. The source was created in Visual Studio 2008 and the Target .Net version is 2.0.

Execution

Open the TokenRobotz.All solution file. The content is shown below.

clip_image014

Leave a Reply

Your email address will not be published. Required fields are marked *