Click here to Skip to main content
Click here to Skip to main content

nTier Code Generator

, 9 Dec 2012
Rate this:
Please Sign up or sign in to vote.
A small utility that generates C# code for each of the layers in an nTiered system.

Introduction

If you are new to n-tier architecture this tool will give you a helping hand to understand what you are building. If you are an old hand at n-tier then I'm not telling you anything new when I say that building all those foundational tiers by hand can be tedious.

If you take a look at the source code you will see that I am simply using a brute force method to write the required code out to the stipulated files and folders. Feel free to improve the code and share it with everyone else.

Background

The power and flexibility that a system architectured with multiple layers provides is something I just can not do without. Business systems are becoming more complex, users demand friendly ways of doing multi-stepped procedures, and business rules always change. I needed a tool that would allow me to reduce the amount of tedious coding that comes with building these foundational layers, but I also wanted to be able to change any code anywhere without having to re-write large portions.

The Code

The code is broken into five sections:
  1. Control behavior
  2. BE code
  3. BLL code
  4. DAL code
  5. UI code

Each section follows the same process:

  1. Get the entered Namespace, folder and class information from the controls
  2. Assign appropriate data types
  3. Write the code to the specified folder

Each project layer is created in the same manner. This is the code that creates the BE layer.

StreamWriter sw = File.CreateText(txtConstants.Text.Trim() + className + ".cs");
sw.WriteLine("using System;"); 
sw.WriteLine("");
sw.WriteLine("namespace " + txtBENamespace.Text.Trim() + ".Constants");
sw.WriteLine("{");
sw.WriteLine("  public enum " + className + "Fields");
sw.WriteLine("  {");
fCount = 1;
foreach (PropertyMap field in fieldList)
{
    if (fCount > 1)
        sw.Write(", " + field.Name);
    else
        sw.Write("    " + field.Name);
    fCount++;
}
sw.WriteLine("");
sw.WriteLine("  }");
sw.WriteLine("}");
sw.Close();
sw.Dispose();

The PropertyMap class holds the attributes of each field in the database table along with the control type assigned to it and the name given to the control. This class is identical in format to the class being written in the BE layer.

Using the tool

Download the compiled utility, either from here or my website. My website (http://veracitysystems.com/downloads/public) will always have the latest version of the code.

Create a new empty solution in Visual Studio, and then create an empty project for each of the layers.

Run the tool, and let it create the code in the folders for each layer. Click the "Show all files" button in the solution explorer and include the new files in your project.

Secondly, if you want to understand how it all works, then download the source. Once again, the latest copy of the source is on my website.

There are a number of comments and assumptions I have made which will be pertinent to newbie n-tier designers, so if you are an experienced coder, you can ignore the rest of this section.

The tool will create the following tiers:

  1. Business Entities (also known as Business Objects) which I will refer to as the BE layer. These are very light weight, extremely small and fast.
  2. Business Logic Layer (also known as Business Rules) which I will refer to as the BLL layer. These too, are small and efficient, and this is where you can place your own business logic.
  3. Data Access Objects which I will refer to as the DAL layer. The workhorse of the foundation layers, these classes communicate to your database/s on behalf of your application.
  4. User Interface which I will refer to as the UI.
There are, of course other layers, two in particular I use all the time. They are Presentation Entities/Objects (PE) and Presentation Logic (PL). The tool does not currently address these latter two, but what it does create is enough to get you well on the way to enjoying the benefits of n-tier.

The following assumptions and results apply:

  1. The tool only produces C# code. There is no VB alternative.
  2. The tool assumes every database table has a Primary Key (PK) set on a single field.
  3. The tool assumes database table names are in the singular form. (Plurals are OK, but you will need to make a small manual change to the DAL code prior to compiling).
  4. The tool only deals with the most common data types. If you are using any of the new data types introduced in SQL 2012 (spatial, etc) then you will need to add these to the source code yourself (or wait until I get around to needing them).
  5. The tool will create code that will ensure you never suffer from a SQL injection attack ever again. All commands sent to the database are parametrized.
  6. All appropriate methods created are available in your Intellisense lists.
  7. All code conforms to Microsoft's coding conventions. (Refer here and here).

The BE code

The first project created by the tool is the Business Entities layer.

Enums

The tool will create a set of enums that you can use to refer to fields, and importantly, pass them as parameters.

AdoDotNetDataProvider

The AdoDotNetDataProvider class handles the common data providers:

  • SQL
  • OLE
  • ODBC

You can, of course, add your own (Oracle, etc.)

The BLL code

The BLL classes mimic their DAL siblings, and maybe that is all you need to do. However, if you have business logic code that is used in more than once place, this is the layer to put it in.

The DAL code

The DAL does not handle any Stored Procedures. If you think about it, SPs hold business logic, and that belongs in the BLL. I know there are a million reasons why SPs are a good thing, and I don't want to get into another argument about the "righteous" way of coding; suffice to say this tool does not support SPs.

Here is the SelectByID() method. It returns a single object of the class type.

swDAL.WriteLine("       public static BE SelectById(Int32 id)");
swDAL.WriteLine("       {");
swDAL.WriteLine("           BE result = new BE();");
swDAL.WriteLine("           using (IDbConnection connection = DataConnection.Connection())");
swDAL.WriteLine("           {");
swDAL.WriteLine("               String sqlQuery = String.Format(\"SELECT * FROM {0} WHERE {1}=@" + 
                key + "\", _tableName, _" + key + ");");
swDAL.WriteLine("               IDbCommand command = DataConnection.Command(connection, sqlQuery);");
swDAL.WriteLine("               AddParameter(command, \"" + key + "\", id );");
swDAL.WriteLine("               connection.Open();");
swDAL.WriteLine("               IDataReader reader = command.ExecuteReader();");
swDAL.WriteLine("               while (reader.Read())");
swDAL.WriteLine("               {");
swDAL.WriteLine("                   result = ToObject(reader);");
swDAL.WriteLine("               }");
swDAL.WriteLine("           }");
swDAL.WriteLine("           if (result." + key + " > 0)");
swDAL.WriteLine("           {");
swDAL.WriteLine("               return LoadObject(result);");
swDAL.WriteLine("           }");
swDAL.WriteLine("           else");
swDAL.WriteLine("           {");
swDAL.WriteLine("               return null;");
swDAL.WriteLine("           }");
swDAL.WriteLine("       }");
swDAL.WriteLine("       #endregion");
swDAL.WriteLine("");

Some things to note about this code:

Each method always returns either an object of the same class, or a list of those same objects. IOW, in the DAL for our customer class, each method returns an object of type "customer", or a list of customer objects.

The call to the ToObject() method returns a single instance of the class object. The LoadObject() method simply casts our object into the data type of the class we are using.

You will see a couple of methods that probably need a brief explanation:

DataAccessObject Class

The DataAccessObject holds methods that handle the parametrization of our database calls and the conversion of one data type to another (e.g.: Image to Byte Array and back again).

DataConnection Class

The DataConnection classes holds methods that handle our connection strings and data providers and links to our AdoDotNetDataProvider defined in the BE layer.

A word about the UI code

The current version of the tool produces UI code assuming you are using the DevExpress suite of controls for WinForms. If enough people request it, I will add support for the standard Microsoft controls that are native to Visual Studio. The BE/BLL/DAL code produced by the tool can be used in all types of applications; it is only the UI code that is WinForm specific.

Wiring it all up

Before you start, create a folder where you want your Visual Studio solution to reside. Run the ORM Tool executable placing the results for each layer in its own project which will reside in its own folder, inside your solution folder. (The tool will prompt you for this automatically.)

Establish the connecting references in each project as follows:

  • In the BLL project, add references to the BE and DAL projects.
  • In the DAL project. add a reference to the BE project.
  • In your UI project, add a reference to the BE and BLL projects.

Compile each project, and you should be right to start creating your GUI forms. If you have the DevExpress WinForms library, you can tick to create the UI layer as well, and the tool will create browse and CRUD forms for each class in the BE layer.

As mentioned before, if you are using plurals in the database table names you will need to make a small change in each table's DAL.

private static String _tableName = "Customers";
// you will need to add the 's' (or other plural form)

One other thing you might like to try. Rather than choosing a database table you can select a text file that contains the field specifications of the table you want to use. If you have multiples text files, one for each table. Place them in a folder outside your solution structure, and leave the class name empty. The tool will know to open each text file in succession and build a BE/BLL/DAL/UI set of classes for each.

Future Functionality

One of the things you will notice is that you can only build the code for a single database table at a time. Sure, you can repeat the steps for each table in the database, like I do right now, but I think it would be helpful if I added a little code that allowed you to point the tool at a database, and it would build the code for every table it found. I am not sure when I will get around to this, as work always has a way for interrupting the good things in life, but send me a request if this is something you will use.

History

While we have been using this tool for over 3 years, this is the first release into the "wild".

License

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

About the Author

MarkChimes2
Architect Veracity Systems
Australia Australia
Mark is a permanent "newbie" when it comes to programming. Having over 25 years of experience starting with TRSDOS and CP/M, along with dBase II, Clipper Autumn 86 and Word Perfect, he has realized that the learning curve for new technologies is just getting steeper and higher. Luckily, he is an optimist, so he hasn't yet realized that he will never reach the top.

Comments and Discussions

 
QuestionExtending Gratitude PinmemberNalin Tharanga Jayasinghe(THARA)8-Jun-14 6:30 
Questionnot able to get db information Pinmemberdangerkirthi19-Dec-12 13:31 
AnswerRe: not able to get db information PinmemberMarkChimes26-Jan-13 11:21 
Questionnot working - i am trying to open project in vs 2012 Pinmemberaisoft27-Nov-12 11:07 
AnswerRe: not working - i am trying to open project in vs 2012 PinmemberMarkChimes210-Dec-12 11:45 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140709.1 | Last Updated 10 Dec 2012
Article Copyright 2012 by MarkChimes2
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid