5 min read

1-tier 3-layer Architecture using a Domain Model

Based on the class diagram in the first part, we will create a new simple 3-layered application using the entities defined in the above domain model. We will create a new ASP.NET Web Project in VS. This time, you should create two new folders inside your root web folder (using the Add New Folder option in VS):

  • BL: This folder will contain all of the business logic domain classes
  • DAL: This folder will contain the data access code files (for each entity)

Layer 1: Data Access Layer (DAL)

First, we will create a DAL class for each entity. We will name each DAL class using this naming pattern: EntityDAL. Let us see the CustomerDAL class:

using DomainModel.BL;
namespace DomainModel.DAL
{
public class CustomerDAL
{
public static void AddCustomer(Customer cs)
{
using (SqlConnection con =
new SqlConnection(SQLHelper.GetConnectionString()))
{
SqlParameter[] par = new SqlParameter[4];
par[0] = new SqlParameter("@customerID", cs.ID);
par[0].Direction = ParameterDirection.Output;
par[1] = new SqlParameter("@name", cs.Name);
par[2] = new SqlParameter("@address", cs.Address);
par[3] = new SqlParameter(
"@phoneNo", cs.PhoneNumber);
int rowNo = SQLHelper.ExecuteNonQuery(
con, CommandType.StoredProcedure,
"OMS_AddCustomer", par);
cs.ID = Convert.ToInt32(par[0].Value);
}
}
public static void DeleteCustomer(int customerID)
{
using (SqlConnection con =
new SqlConnection(SQLHelper.GetConnectionString()))
{
SqlParameter[] par = new SqlParameter[1];
par[0] = new SqlParameter("@customerID", customerID);
int rowNo = SQLHelper.ExecuteNonQuery(
con, CommandType.StoredProcedure,
"OMS_DeleteCustomer", par);
}
}
public static void UpdateCustomer(Customer cs)
{
using (SqlConnection con = new
SqlConnection(SQLHelper.GetConnectionString()))
{
SqlParameter[] par = new SqlParameter[4];
par[0] = new SqlParameter("@customerID", cs.ID);
par[1] = new SqlParameter("@address", cs.Address);
par[2] = new SqlParameter("@name", cs.Name);
par[3] = new SqlParameter(
"@phoneNo", cs.PhoneNumber);
int rowNo = SQLHelper.ExecuteNonQuery(
con, CommandType.StoredProcedure,
"OMS_UpdateCustomer", par);
}
}
public static void GetCustomer(Customer cs)
{
using (SqlConnection con =
new SqlConnection(SQLHelper.GetConnectionString()))
{
SqlParameter[] par = new SqlParameter[1];
par[0] = new SqlParameter("@customerID", customerID);
using (SqlDataReader dr =
SQLHelper.ExecuteReader(con,
CommandType.StoredProcedure,
"OMS_GetCustomer", par))
{
c = new Customer();
while (dr.Read())
{
c.Name =
SQLHelper.CheckStringNull(dr["Name"]);
c.PhoneNumber =
SQLHelper.CheckStringNull(dr["PhoneNo"]);
c.Address =
SQLHelper.CheckStringNull(dr["Address"]);
c.ID = SQLHelper.CheckIntNull(dr["ID"]);
}
}
}
}
public static List<Customer> GetAllCustomers()
{
List<Customer> cuList = new List<Customer>();
using (SqlConnection con =
new SqlConnection(SQLHelper.GetConnectionString()))
{
using (SqlDataReader dr =
SQLHelper.ExecuteReader(con,CommandType.
StoredProcedure,"OMS_GetAllCustomer"))
{
while (dr.Read())
{
Customer customer = new Customer();
customer.Name =
SQLHelper.CheckStringNull(dr["Name"]);
customer.PhoneNumber =
SQLHelper.CheckStringNull(dr["PhoneNo"]);
customer.Address =
SQLHelper.CheckStringNull(dr["Address"]);
customer.ID =
SQLHelper.CheckIntNull(dr["ID"]);
cuList.Add(customer);
}
}
}
return cuList;
}
}//end class
}

Here, we have used the SqlHelper class, which contains generic data access utility methods, so that we can avoid code repletion.

Layer 2: Business Layer (BL)

Next, we will create classes for each of the domain entities. We will put all of these classes under the new BL folder with this namespace: DomainModel.BL. Create a new C# class file named Customer.cs under the BL folder. Here is the first Customer class:

using DomainModel.DAL;
namespace DomainModel.BL
{
public class Customer
{
private int _ID;
private string _name;
private string _address;
private string _phoneNumber;
private List<Customer> _customerCollection;
public int ID
{
get { return _ID; }
set { _ID = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Address
{
get { return _address; }
set { _address = value; }
}
public string PhoneNumber
{
get { return _phoneNumber; }
set { _phoneNumber = value; }
}
public List<Customer> CustomerCollection
{
get { return _customerCollection; }
set { _customerCollection = value; }
}
public void Add()
{
CustomerDAL.AddCustomer(this);
}
public void Delete(int customerID)
{
CustomerDAL.DeleteCustomer(this.ID);
}
public void Update()
{
CustomerDAL.UpdateCustomer(this);
}
public void Load()
{
CustomerDAL.GetCustomer(this.ID);
}
public void GetAll()
{
this.CustomerCollection = CustomerDAL.GetAllCustomers();
}
}//end class
}//end namespace

The CustomerDAL class is pretty simple: we are fetching the data from the database using data readers, and performing all data related operations using the Customer business object. This Customer class is defined in the Customer.cs class we created earlier. This BL class is calling DAL methods, so it needs a reference to the DAL namespace (using DomainModel.DAL). Similarly, the DAL class we created earlier used Customer business objects. That’s why it also needed the BL namespace.

We are using generics to create a collection of Customer objects. The BL communicates with DAL to get the data and perform updates. Now, we will see how the UI (which is under a different namespace) talks to BL without even knowing about DAL.

Layer 3: The UI Layer

Here is the code in the AllCustomers.aspx.cs page that shows a list of all of the customers from the DB (there is a data list on the web form, which will show a list of the customers):

using DomainModel.BL;
namespace DomainModel.UI
{
//page load
private void FillAllCustomers()
{
Customer c = new Customer();
c.GetAll();
List<Customer> cuList = c.CustomerCollection;
dtlstAllCustomer.DataSource = cuList;
dtlstAllCustomer.DataBind();
}
}

So in the UI class, we neither have any data access code nor are we calling data access class methods from this layer (as was the case with the 1-tier 2-layer style we saw earlier in this article). We have a reference to the BL layer (using DomainModel.BL), and we are using the Customer business object to return a generic list of customer objects, which we are binding to the data list control (showing a list of all the customers). So the GUI layer does not know anything about the DAL layer, and is completely independent of it.

The idea here is to understand how a 3-Layer architecture can provide more flexibility and loose-coupling to your project. In the next section, we will learn how we can use object data source controls to implement a 3-layer architecture without writing much code ourselves.

LEAVE A REPLY

Please enter your comment!
Please enter your name here