Click here to Skip to main content
Click here to Skip to main content
Go to top

Understanding Three Layer Architecture and its Implementation in C# .NET

, 8 Nov 2013
Rate this:
Please Sign up or sign in to vote.
What is three layer architecture and how to implement it.

Introduction

To design software effectively we prefer to take a multilayer architecture. That approach has been adopted by the industry to write efficient code. Change management becomes very easy in this style of coding. Let’s discuss the approach briefly. A three-layer process model helps us to work efficiently initially. After some point of time if any change comes in the business logic that can be done easily by making the particular change on the particular layer. For example, the change in business logic layer will not affect the other two layers namely Data Access and UI.

How the three layers are connected?

Connection between three layers

Dataflow Diagram of Three Layer Architecture

DFD of Three Layer Architecture

Implementation of DAL

Before implementing DAL, you first need to know what DAL or Data Access Layer is and what it contains.

In Data Access Layer, data may be any database (Oracle, SQL Server, Access, PostgreSQL, MySQL, etc.) or any file. That means, where you store the data. And this layer is the one and only connectivity between your application and that data.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
 
namespace DAL
// Notice this name of this namespace. In BLL we will use
// this 'DAL' namespace according to the above picture
{
    class Database
    {
        internal string UserName { get; set; }
 
        internal string Password { get; set; }
 
        internal string ServerName { get; set; }
 
        internal string DatabaseName { get; set; }
 
        internal string ConnectionString
        {
            get { return "Data Source=" + ServerName + ";Initial Catalog=" + 
              DatabaseName + ";Persist Security Info=True;User ID=" + 
              UserName + ";Password=" + Password; }
        }
 
        /// <summary>
        /// Insert, Update and Delete in the database through this method
        /// </summary>
        /// The SQL Query or the name of the Stored Procedure
        /// The values which you have to insert, update, or delete
        /// If the first parameter "sql"
        /// is any name of the stored procedure then it must be true
        /// True for successful execution, otherwise False
        public bool InsertUpdateDelete(string sql, Dictionary parameters, bool isProcedure)
        {
            using (SqlConnection sqlConnection = new SqlConnection(ConnectionString))
            {
                sqlConnection.Open();
 
                using (SqlCommand sqlCommand = new SqlCommand(sql, sqlConnection))
                {
                    if (isProcedure)
                        sqlCommand.CommandType = 
                           System.Data.CommandType.StoredProcedure;
                    else sqlCommand.CommandType = System.Data.CommandType.Text;
 
                    // Adding parameters using Dictionary...
                    foreach (KeyValuePair parameter in parameters)
                        sqlCommand.Parameters.Add(new SqlParameter(parameter.Key, parameter.Value));
                    if (sqlCommand.ExecuteNonQuery() > 0) return true;
                    else return false;
                }
            }
        }
 
        /// <summary>
        /// Select from database through this method
        /// </summary>
        /// The SQL Query or the name of the Stored Procedure
        /// If the first parameter "sql" is any name of the stored procedure then it must be true
        /// The parameters which you want to pass through WHERE clause in SELECT Query
        /// The resultant table aganist the select query or the stored procedure
        public DataTable Select(string sql, bool isProcedure, Dictionary parameters = null)
        {
            using (SqlConnection sqlConnection = new SqlConnection(ConnectionString))
            {
                sqlConnection.Open();
                using (SqlCommand sqlCommand = new SqlCommand(sql, sqlConnection))
                {
                    if (isProcedure) sqlCommand.CommandType = CommandType.StoredProcedure;
                    else sqlCommand.CommandType = CommandType.Text;
                    if (parameters != null)
                        foreach (KeyValuePair parameter in parameters)
                            sqlCommand.Parameters.Add(new SqlParameter(parameter.Key, parameter.Value));
                    using (SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand))
                    {
                        using (DataTable dt = new DataTable())
                        {
                            sqlDataAdapter.Fill(dt);
                            return dt;
                        }
                    }
                }
            }
        }
    }
}

Implementation of BLL

Before implementing BLL, you first need to know what BLL or Business Logic Layer is and what it contains.

Roughly speaking, you can think a 'name of the table' as a 'name of the class', 'name of the columns' as a 'name of the data members or properties' and the DDL and DML operations as methods of that class.

Let's implement what I've said:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using DAL;    // Notice this as I've already told you, I'm doing accordingly...

namespace BLL
{
    class EmployeeBLL
    {
        /* This properties are the columns of the table 'Employee' */
        public long EmployeeId { get; set; }
        public string EmployeeName { get; set; }
        public string EmployeeAddress { get; set; }
        public double Salary { get; set; }
        public DateTime DOJ { get; set; }
 
        
        /* I've just implement four basic database operations: Insert, Update, Delete, Select */
 
        public bool InsertEmployee()
        {
            Database db = InitializeDatabase();
 
            string sqlQuery = "INSERT INTO [Employee] ";
            sqlQuery += "(EmployeeName, EmployeeAddress, Salary, DOJ) ";
            sqlQuery += "VALUES ";
            sqlQuery += "(@EmployeeName, @EmployeeAddress, @Salary, @DOJ)";
 
            Dictionary parameters = new Dictionary();
            parameters.Add("@EmployeeName", EmployeeName);
            parameters.Add("@EmployeeAddress", EmployeeAddress);
            parameters.Add("@Salary", Salary);
            parameters.Add("@DOJ", DOJ);
 
            return db.InsertUpdateDelete(sqlQuery, parameters, false);
        }
 
        public bool UpdateEmployee()
        {
            Database db = InitializeDatabase();
 
            string sqlQuery = "UPDATE [Employee] SET ";
            sqlQuery += "EmployeeName=@EmployeeName, EmployeeAddress=@EmployeeAddress, Salary=@Salary, DOJ=@DOJ ";
            sqlQuery += "WHERE EmployeeId=@EmployeeId";
 
            Dictionary parameters = new Dictionary();
            parameters.Add("@EmployeeId", EmployeeId);
            parameters.Add("@EmployeeName", EmployeeName);
            parameters.Add("@EmployeeAddress", EmployeeAddress);
            parameters.Add("@Salary", Salary);
            parameters.Add("@DOJ", DOJ);
 
            return db.InsertUpdateDelete(sqlQuery, parameters, false);
        }
 
        public bool DeleteEmployee()
        {
            Database db = InitializeDatabase();
 
            string sqlQuery = "DELETE [Employee] WHERE EmployeeId=@EmployeeId";
 
            Dictionary parameters = new Dictionary();
            parameters.Add("@EmployeeId", EmployeeId);
 
            return db.InsertUpdateDelete(sqlQuery, parameters, false);
        }
 
        public DataTable SelectEmployee()
        {
            Database db = InitializeDatabase();
            
            string sqlQuery = "SELECT EmployeeId AS Id, EmployeeName AS Name, " + 
              "EmployeeAddress AS Address, Salary, DOJ AS 'Joining Date' FROM Employee";
 
            return db.Select(sqlQuery, false);
        }
 
        public DataRow SelectEmployeeById()
        {
            Database db = InitializeDatabase();
            
            string sqlQuery = "SELECT EmployeeName AS Name, EmployeeAddress " + 
              "AS Address, Salary, DOJ AS 'Joining Date' ";
            sqlQuery += "FROM Employee WHERE EmployeeId=@EmployeeId";
 
            Dictionary parameters = new Dictionary();
            parameters.Add("@EmployeeId", EmployeeId);
 
            return db.Select(sqlQuery, false, parameters).AsEnumerable().First();
        }
 
        private Database InitializeDatabase()
        {
            Database db = new Database();
            db.UserName = "sa";
            db.Password = "server2008";
            db.ServerName = "(local)";
            db.DatabaseName = "DebopamDB";
            return db;
        }
    }
}

Implementation of UI Layer

UI Layer is the User Interface Layer. This layer contains Web Forms and its controls for Web based applications. And Windows Forms and its controls for Desktop based applications.

I've implemented a Desktop based application demo. In the next version I'll show you how you can implement a Web based application using the same DAL and BLL that I've implemented here.

The Main form

The Main Window Form

Behind the Main Form:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BLL;
// Notice this, I'm using the namespace of BLL, not DAL as described above.

namespace ThreeLayerArchitectureDemo
{
    public partial class FormManageEmployee : Form
    {
        EmployeeBLL employee = new EmployeeBLL();
 
        public FormManageEmployee()
        {
            InitializeComponent();
        }
 
        private void FormManageEmployee_Load(object sender, EventArgs e)
        {
            FillGridView();
        }
 
        // Code aganist 'Insert' button
        private void btnInsert_Click(object sender, EventArgs e)
        {
            using (FormEditUpdateEmployee frmEditUpdateEmp = new FormEditUpdateEmployee())
            {
                frmEditUpdateEmp.EmployeeId = 0;
                if (frmEditUpdateEmp.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    employee = frmEditUpdateEmp.ToEmployee();
                    if (employee.InsertEmployee())
                    {
                        FillGridView();
                        MessageBox.Show("Successfully Inserted", "Success", 
                          MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    else
                        MessageBox.Show("Error during Inserting", "Error", 
                          MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else return;
            }
        }
 
        private void FillGridView()
        {
            grdViewEmployee.DataSource = employee.SelectEmployee();
        }
 
        // Code aganist 'Edit' button
        private void btnEdit_Click(object sender, EventArgs e)
        {
            using (FormEditUpdateEmployee frmEditUpdateEmp = new FormEditUpdateEmployee())
            {
                frmEditUpdateEmp.EmployeeId = long.Parse(grdViewEmployee.CurrentRow.Cells["Id"].Value.ToString());
                if (frmEditUpdateEmp.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    employee = frmEditUpdateEmp.ToEmployee();
                    if (employee.UpdateEmployee())
                    {
                        FillGridView();
                        MessageBox.Show("Successfully Updated", 
                          "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    else
                        MessageBox.Show("Error during Updating", 
                          "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                    return;
            }
        }
 
        // Code aganist 'Delete' button
        private void btnDelete_Click(object sender, EventArgs e)
        {
            employee.EmployeeId = long.Parse(grdViewEmployee.CurrentRow.Cells["Id"].Value.ToString());
            employee.EmployeeName = grdViewEmployee.CurrentRow.Cells["Name"].Value.ToString();
            if (MessageBox.Show("Delete " + employee.EmployeeName + "?", 
                  "Delete Employee?", MessageBoxButtons.YesNo, 
                  MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                if (employee.DeleteEmployee())
                {
                    FillGridView();
                    MessageBox.Show("Successfully Deleted", 
                      "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                    MessageBox.Show("Error during Deleting", 
                      "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            else
                return;
        }
    }
}

The Insert/Edit Form

Form for Insert or Edit

Behind the Insert/Edit form:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BLL;
 
namespace ThreeLayerArchitectureDemo
{
    public partial class FormEditUpdateEmployee : Form
    {
        EmployeeBLL employee = new EmployeeBLL();
 
        public long EmployeeId
        {
            get { return long.Parse(this.txtName.Tag.ToString()); }
            set
            {
                if (value == 0)
                {
                    this.txtName.Text = null;
                    this.txtName.Tag = 0;
                    this.txtAddress.Text = null;
                    this.txtSalary.Text = null;
                    this.dateDOJ.Value = DateTime.Today.Date;
                }
                else
                {
                    employee.EmployeeId = value;
                    DataRow dr = employee.SelectEmployeeById();
                    this.txtName.Text = dr["Name"].ToString();
                    this.txtName.Tag = value;
                    this.txtAddress.Text = dr["Address"].ToString();
                    this.txtSalary.Text = dr["Salary"].ToString();
                    this.dateDOJ.Value = DateTime.Parse(dr["Joining Date"].ToString());
                }
            }
        }
 
        internal EmployeeBLL ToEmployee()
        {
            employee.EmployeeId = long.Parse(this.txtName.Tag.ToString());
            employee.EmployeeName = this.txtName.Text;
            employee.EmployeeAddress = this.txtAddress.Text;
            employee.Salary = double.Parse(this.txtSalary.Text);
            employee.DOJ = this.dateDOJ.Value;
            return employee;
        }
 
        public FormEditUpdateEmployee()
        {
            InitializeComponent();
        }
 
        // Code aganist 'Save' button
        private void btnSave_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.Close();
        }
 
        // Code aganist 'Cancel' button
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.Close();
        }
    }
}

Advantages of Using Three Layer Architecture

  • Scalability: The application servers can be deployed on many machines, the database no longer requires a connection from every client.
  • Reusability: You can reuse the Business Logic Layer (BLL) i.e. middle layer with different user interfaces like ASP.NET Web Form, ASP.NET Web Service, .NET Window Form etc. You can reuse the Database Access Layer (DAL) i.e. top layer with different project.
  • Improve Data Integrity: The BLL i.e. middle layer can ensure that only valid data is allowed to be inserted, updated or deleted in the database.
  • Improve Security: Since the client does not have direct access to the database. BLL is more generally secure since it is placed on a more secure central server.
  • Reduce Distribution: Changes to BLL/DLL only need to be updated on application server & do not have to be disturbed to all clients.
  • Hidden Database Structure: Since the actual structure of the database is hidden from the user.
  • Improve Availability

Disadvantages of Using Three Layer Architecture

  • Increase developer’s complexity and effort
  • In general 3-Layer architecture is more complex to build compared to 2-Layer architecture
  • Point of communication is doubled

Points of Interest

When you implement this code you'll also learn to use Dictionary, using, and internal in C#.

History

  • Version 1.0: Nov, 2013.

License

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

Share

About the Author

Debopam Pal
Software Developer National Informatics Centre (NIC)
India India
Hello! Myself Debopam Pal. I've completed my MCA degree from West Bengal University of Technology at 2013. I'm from India. I’ve started to work with MS Technologies in 2013 specially in C# 4.0, ASP.NET 4.0. I've also worked in PHP 5. Now I work in JAVA/J2EE, Struts2. Currently I'm involved in a e-Governance Project since Jan, 2014. In my leisure time I write Blog, Articles as I think that every developer should contribute something otherwise resource will be finished one day. Thank you for your time.
 
Visit: Linkedin Profile | Facebook Profile | Google+ Profile | CodeProject Profile
Follow on   Google+   LinkedIn

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 1 PinmemberFrans Vander Meiren11-Nov-13 23:37 
GeneralRe: My vote of 1 PinmemberDebopam Pal12-Nov-13 0:15 
GeneralMy vote of 4 PinmemberMember 102733658-Nov-13 23:01 
GeneralMy vote of 1 PinprofessionalRolando CC8-Nov-13 11:58 
GeneralThoughts PinprofessionalPIEBALDconsult8-Nov-13 10:25 
GeneralMy vote of 1 PinmemberKeesDijk8-Nov-13 4:17 
Question[My vote of 2] Unable to find those feature PinprofessionalSuvabrata Roy7-Nov-13 22:44 
Generalcomment PinmemberMember 103867917-Nov-13 5:27 
GeneralRe: comment PinmemberDebopam Pal7-Nov-13 5:37 
GeneralGood Initiative Debopam PinmemberMr.Sourav.Maitra7-Nov-13 2:35 
GeneralRe: Good Initiative Debopam PinmemberDebopam Pal7-Nov-13 3:07 
GeneralRe: Good Initiative Debopam PinmemberMr.Sourav.Maitra7-Nov-13 20:54 
GeneralMy vote of 1 PinmembervSoares7-Nov-13 1:43 
GeneralMy vote of 1 PinmemberAlexandru Lungu7-Nov-13 1:41 
GeneralYou've got it all wrong PinmemberAlexandru Lungu7-Nov-13 1:40 
GeneralRe: You've got it all wrong PinmemberDebopam Pal7-Nov-13 3:04 
GeneralMy vote of 5 PinmemberSunny_Kumar_7-Nov-13 0:14 

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.140916.1 | Last Updated 8 Nov 2013
Article Copyright 2013 by Debopam Pal
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid