designing Three Tier Architecture in C #


Introduction

3-Tier architecture consist of three basic layers

1)  UI or Presentation Layer
2) Business Access Layer (BAL) or Business Logic Layer
3) Data Access Layer (DAL).

Presentation Layer (UI)
cotains web or windows form where data is presented to the user or input is taken from the user.

Business Access Layer (BAL) or Business Logic Layer
BAL contains business logic, validations or calculations related with the data

Data Access Layer (DAL)
DAL contains methods that helps business layer to connect the data and perform required action, might be returning data or manipulating data (insert, update, delete etc
Designing 3-Tier Architecture


For the ease of understanding, I have created BAL, DAL into the App_Code folder. In real scenario, you should create separate projects for BAL, DAL (as Class Library) and UI (as Web project) and reference your BAL into UI.




Data Access Layer (DAL)
Lets start with desiging 3-Tier architecture.
                    To do that lets proceed with DAL, BAL and then UI. Add a class named by right clicking App_Code folder.  and copy-paste folowing code (Your can overwrite your default written code for the class file by pasting this code). Here, I have assumed that you will create the respective stored procedure yourself into the database


Code for Data Access Layer

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Data.SqlClient;





    /// <summary>

    /// Summary description for PersonDAL3

    /// </summary>

    public class PersonDAL3

    {

        string connStr = ConfigurationManager.ConnectionStrings["TutTestConn"].ToString();



        public PersonDAL3()

        {



        }



        /// <summary  >

        /// Used to insert records into database

        /// </summary>

        /// <param name="firstName"></param>

        /// <param name="lastName"></param>

        /// <param name="age"></param>

        /// <returns></returns>

        public int Insert(string firstName, string lastName, int age)

        {

            SqlConnection conn = new SqlConnection(connStr);

            conn.Open();

            SqlCommand dCmd = new SqlCommand("InsertData", conn);

            dCmd.CommandType = CommandType.StoredProcedure;

            try

            {

                dCmd.Parameters.AddWithValue("@firstName", firstName);

                dCmd.Parameters.AddWithValue("@lastName", lastName);

                dCmd.Parameters.AddWithValue("@age", age);

                return dCmd.ExecuteNonQuery();

            }

            catch

            {

                throw;

            }

            finally

            {

                dCmd.Dispose();

                conn.Close();

                conn.Dispose();

            }

        }





        /// <summary>

        /// Update record into database

        /// </summary>

        /// <param name="personID"></param>

        /// <param name="firstName"></param>

        /// <param name="lastName"></param>

        /// <param name="age"></param>

        /// <returns></returns>

        public int Update(int personID, string firstName, string lastName, int age)

        {

            SqlConnection conn = new SqlConnection(connStr);

            conn.Open();

            SqlCommand dCmd = new SqlCommand("UpdateData", conn);

            dCmd.CommandType = CommandType.StoredProcedure;

            try

            {

                dCmd.Parameters.AddWithValue("@firstName", firstName);

                dCmd.Parameters.AddWithValue("@lastName", lastName);

                dCmd.Parameters.AddWithValue("@age", age);

                dCmd.Parameters.AddWithValue("@personID", personID);

                return dCmd.ExecuteNonQuery();

            }

            catch

            {

                throw;

            }

            finally

            {

                dCmd.Dispose();

                conn.Close();

                conn.Dispose();

            }

        }



        /// <summary>

        /// Load all records from database

        /// </summary>

        /// <returns></returns>

        public DataTable Load()

        {

            SqlConnection conn = new SqlConnection(connStr);

            SqlDataAdapter dAd = new SqlDataAdapter("LoadAll", conn);

            dAd.SelectCommand.CommandType = CommandType.StoredProcedure;

            DataSet dSet = new DataSet();

            try

            {

                dAd.Fill(dSet, "PersonTable");

                return dSet.Tables["PersonTable"];

            }

            catch

            {

                throw;

            }

            finally

            {

                dSet.Dispose();

                dAd.Dispose();

                conn.Close();

                conn.Dispose();

            }

        }



        /// <summary>

        /// Delete record from database

        /// </summary>

        /// <param name="personID"></param>

        /// <returns></returns>

        public int Delete(int personID)

        {

            SqlConnection conn = new SqlConnection(connStr);

            conn.Open();

            SqlCommand dCmd = new SqlCommand("DeleteData", conn);

            dCmd.CommandType = CommandType.StoredProcedure;

            try

            {

                dCmd.Parameters.AddWithValue("@personID", personID);

                return dCmd.ExecuteNonQuery();

            }

            catch

            {

                throw;

            }

            finally

            {

                dCmd.Dispose();

                conn.Close();

                conn.Dispose();

            }

        }



    }



connStr  -  member variable that is getting database connection string from my web.config file that is being used through out the class.
                  I have separate method for inserting, deleting, updating records into database and loading records from database. I am not goint into details of how I am connecting database and manipulating the data just to make this tutorials short.

Business Access Layer (BAL)

Now, create a class named PersonBAL3 into App_Code folder by right clicking it and write respective methods for calling Insert, Delete, Update and Load methods of Data Access Layer class file (PersonDAL3)  As we don't have any business logic here so simply instantiate the PersonDAL3 class of DAL and call methods. Below is the code for BAL (Your can overwrite your default written code for the class file by pasting this code).

Code for Business Access Layer

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;



    /// <summary>

    /// Summary description for PersonBAL3

    /// </summary>

    public class PersonBAL3

    {

        public PersonBAL3()

        {



        }



        /// <summary>

        /// insert records into database

        /// </summary>

        /// <param name="firstName"></param>

        /// <param name="lastName"></param>

        /// <param name="age"></param>

        /// <returns></returns>

        public int Insert(string firstName, string lastName, int age)

        {

            PersonDAL3 pDAL = new PersonDAL3();

            try

            {

                return pDAL.Insert(firstName, lastName, age);

            }

            catch

            {

                throw;

            }

            finally

            {

                pDAL = null;

            }

        }



        /// <summary>

        /// Update records into database

        /// </summary>

        /// <param name="personID"></param>

        /// <param name="firstName"></param>

        /// <param name="lastName"></param>

        /// <param name="age"></param>

        /// <returns></returns>

        public int Update(int personID, string firstName, string lastName, int age)

        {

            PersonDAL3 pDAL = new PersonDAL3();

            try

            {

                return pDAL.Update(personID, firstName, lastName, age);

            }

            catch

            {

                throw;

            }

            finally

            {

                pDAL = null;

            }

        }



        /// <summary>

        /// Load records from database

        /// </summary>

        /// <returns></returns>

        public DataTable Load()

        {

            PersonDAL3 pDAL = new PersonDAL3();

            try

            {

                return pDAL.Load();

            }

            catch

            {

                throw;

            }

            finally

            {

                pDAL = null;

            }

        }



        /// <summary>

        /// Delete record from database

        /// </summary>

        /// <param name="personID"></param>

        /// <returns></returns>

        public int Delete(int personID)

        {

            PersonDAL3 pDAL = new PersonDAL3();

            try

            {

                return pDAL.Delete(personID);

            }

            catch

            {

                throw;

            }

            finally

            {

                pDAL = null;

            }

        }



    }


Presentation Layer

Till now we haev our Business Access Layer and Database Access Layer ready. Now we have to write our Presentation Layer that will use our Business Access Layer methods. Lets create a form that will have three textboxes for FirstName, LastName and Height.

Presentation Layer




Create an Insert.aspx page (make is as Startup page) and copy paste following code to bring the insert form something like displaying in the picture.
Code for Insert Record form

<asp:Label ID="lblMessage" runat="Server" ForeColor="red" EnableViewState="False"></asp:Label>

        <table style="border:2px solid #cccccc;">

            <tr style="background-color:#507CD1;color:White;">

                <th colspan="3">Add Records</th>

            </tr>

            <tr>

                <td>

                    First Name:

                </td>

                <td>

                    <asp:TextBox ID="txtFirstName" runat="Server"></asp:TextBox>

                </td>

                <td>

                    <asp:RequiredFieldValidator ID="req1" runat="Server" Text="*" ControlToValidate="txtFirstName"

                         Display="dynamic"></asp:RequiredFieldValidator>

                </td>

            </tr>

            <tr>

                <td>

                    Last Name:

                </td>

                <td>

                    <asp:TextBox ID="txtLastName" runat="Server"></asp:TextBox>

                </td>

                <td>

                    <asp:RequiredFieldValidator ID="req2" runat="Server" Text="*" ControlToValidate="txtLastName"

                      Display="dynamic"></asp:RequiredFieldValidator>

                </td>

            </tr>

            <tr>

                <td>

                    Height:

                </td>

                <td>

                    <asp:TextBox ID="txtHeight" runat="Server" Columns="4"></asp:TextBox>

                </td>

                <td>

                    <asp:RequiredFieldValidator ID="req3" runat="Server" Text="*" ControlToValidate="txtHeight"

                        Display="dynamic"></asp:RequiredFieldValidator>

                    <asp:CompareValidator ID="Comp1" runat="Server" Text="Only integer" ControlToValidate="txtHeight"

                       Operator="DataTypeCheck" Type="Integer"></asp:CompareValidator>

                </td>

            </tr>

            <tr>

                <td>&nbsp;</td>

                <td>

                    <asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClick="AddRecords" />

                </td>

            </tr>

        </table>



Now, lets write method that will fire when Submit button will be clicked on the from.
Code for AddRecords method

protected void AddRecords(object sender, EventArgs e)

    {

        //Lets validate the page first

        if (!Page.IsValid)

            return;



        int intResult = 0;

        // Page is valid, lets go ahead and insert records

        // Instantiate BAL object

        PersonBAL3 pBAL = new PersonBAL3();

        // Instantiate the object we have to deal with

        string firstName = txtFirstName.Text;

        string lastName = txtLastName.Text;

        int Height = Int32.Parse(txtHeight.Text);

        

        try

        {

            intResult = pBAL.Insert(firstName, lastName, Height);

            if (intResult > 0)

                lblMessHeight.Text = "New record inserted successfully.";

            else

                lblMessHeight.Text = "FirstName [<b>"+ txtFirstName.Text +"</b>] alredy exists, try another name";



        }

        catch (Exception ee)

        {

            lblMessHeight.Text = ee.MessHeight.ToString();

        }

        finally

        {

            pBAL = null;

        }        

    }


In the above code, first I am validating the page by using Page.IsValid method just to check if correct data has been entered. Then I have instantiated PersonBAL3 and calling Insert method of it (pBAL.Insert) by passing firstName, lastName, Height as parameter.

Dispalying Records into GridView



Create a .aspx file called List.aspx and create a GridView. To list the record into GridView that will also enable us to Edit, Delete record, copy paste following code.


Code to Load records and Displaying Records into GridView

private DataTable BindGrid()

    {

        PersonBAL3 p = new PersonBAL3();



        try

        {

            DataTable dTable = p.Load();

            GridView1.DataSource = dTable;

            GridView1.DataBind();

        }

        catch (Exception ee)

        {

            lblMessHeight.Text = ee.MessHeight.ToString();

        }

        finally

        {

            p = null;

        }



        return dTable;

    }


In the above method I am instantiating PersonBAL3 class and calling Load method to get the record into DataTable and binding it into GridView.

Code to Delete Records

protected void DeleteRecord(object sender, GridViewDeleteEventArgs e)

    {

        int personID = Int32.Parse(GridView1.DataKeys[e.RowIndex].Value.ToString());

       



        // instantiate BAL

        PersonBAL3 pBAL = new PersonBAL3();

        try

        {

            pBAL.Delete(personID);



            lblMessHeight.Text = "Record Deleted Successfully.";

        }

        catch (Exception ee)

        {

            lblMessHeight.Text = ee.MessHeight.ToString();

        }

        finally

        {

            pBAL = null;

        }



        GridView1.EditIndex = -1;

        // Refresh the list

        BindGrid();

    }


Above method will fire when Delete link will be clicked on the GridView. In the above code, I am instantiating PersonBAL3 and calling Delete method by passing personID as parameter so that select reocrds will be deleted from datbase.

Code to Update records

protected void UpdateRecord(object sender, GridViewUpdateEventArgs e)

    {

        int personID = Int32.Parse(GridView1.DataKeys[e.RowIndex].Value.ToString());

        int intResult = 0;

        GridViewRow row = GridView1.Rows[e.RowIndex];



        TextBox tFN = (TextBox) row.FindControl("txtFName");

        TextBox tLN = (TextBox)row.FindControl("txtLName");

        TextBox tHeight = (TextBox)row.FindControl("txtHeight");



        // instantiate BAL

        PersonBAL3 pBAL = new PersonBAL3();



        try

        {

            intResult = pBAL.Update(personID, tFN.Text, tLN.Text, int.Parse(tHeight.Text));

            if (intResult > 0)

                lblMessHeight.Text = "Record Updated Successfully.";

            else

                lblMessHeight.Text = "Record couldn't updated";

        }

        catch (Exception ee)

        {

            lblMessHeight.Text = ee.MessHeight.ToString();

        }        finally

        {

            pBAL = null;

        }



        GridView1.EditIndex = -1;

        // Refresh the list

        BindGrid();

    }


Above method will fire when Update link will be clicked for a particular row of the GridView in edit mode. In the above method, I am instantiating PersonBAL3 and calling the Update method by passing required parameters.

Now we have all set to go, now just run your project and try inserting records. You can also navigate to another page your created (list.aspx) and try updating, deleting records.

Conclusion

By using 3-Tier architecture in your project you can achive

1. Seperation - the functionality is seperated from the data access and presentation so that it is more maintainable
2. Independence - layers are established so that if one is modified (to some extent) it will not affect other layers.
3. Reusability - As the layers are seperated, it can exist as a module that can be reused by other application by referencing it.

Thanks!!!