Now that we have had a look at the design architecture and understand the role of the collection objects in providing a consistent interface to the consumers of the business logic layer of the application, let us consider an example application that implements the above architecture. For the purposes of this article, we will create an end-to-end implementation that uses the Employees table of the Northwind database. We will display employees' details using the ASP.NET Web application and expose the employees' details using ASP.NET Web services layer. For this example, we will also implement the business logic layer and data access layer. We will start by looking at the data access layer. Data Access Layer Implementation
The data access layer basically contains the methods that are used to execute SQL statements against the SQL Server database. For the purposes of this article, create a new Visual C# class library project named DataAccess. After the project is created, rename the default class from class1 to EmployeeDB. As the name suggests, EmployeeDB class performs operations against the Employees table in the Northwind database. In this example, we will just consider a Get method named GetEmployees that returns details of all the employees from the Northwind database. We will start by importing all the required namespaces.
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace DataAccess
{
public class EmployeeDB
{
public
EmployeeDB()
{
}
public
DataSet GetEmployees()
{
string
connString =
ConfigurationSettings.AppSettings["connectionString"];
using
(SqlConnection conn = new SqlConnection(connString))
{
string
sql = "Select EmployeeID, LastName,
FirstName,
Title from Employees";
SqlDataAdapter
adapter = new SqlDataAdapter(sql,conn);
DataSet
employeesDataSet = new DataSet();
adapter.Fill(employeesDataSet);
return
employeesDataSet;
}
}
}
}
In the GetEmployees method, we start by retrieving the connection string from the web.config file. After that we create an instance of the SqlConnection object and supply the connection string as an argument. Then we create an instance of the SqlDataAdapter object, passing in the SQL statement and the SqlConnection object as arguments to its constructor. Finally, we execute the SQL statement and fill the DataSet object with the results of the execution of the SQL query and then return the DataSet to the calling method.
Business Logic Layer Implementation
As mentioned before, the business logic layer contains all the business logic required for the application. In this example, we will create a new Visual C# class library project named BusinessLogic and rename the default class from class1 to EmployeeBiz. The EmployeeBiz contains a method named GetEmployees that invokes the EmployeeDB class of the data access layer for all of its functionalities. The code required for implementing the EmployeeBiz class is shown below.
using System;
using System.Data;
using DataAccess;
using ObjectDeclarations;
namespace BusinessLogic
{
public class EmployeeBiz
{
public
EmployeeBiz()
{
}
public
Employees GetEmployees()
{
Employees
empCol = new Employees();
EmployeeDB
emp = new EmployeeDB();
DataSet
employeesDataSet = emp.GetEmployees();
//Get
reference to the first DataTable
DataTable
employeesTable = employeesDataSet.Tables[0];
foreach(DataRow
row in employeesTable.Rows)
{
Employee
employee = new Employee();
employee.EmployeeID=Convert.ToInt32(row["EmployeeID"]);
employee.LastName
= Convert.ToString(row["LastName"]);
employee.FirstName
= Convert.ToString(row["FirstName"]);
employee.Title
= Convert.ToString(row["Title"]);
empCol.Add(employee);
}
return
empCol;
}
}
}
In the GetEmployees method, we invoke the data access layer method and get the employee details in the form of a DataSet object. After we get the DataSet object, we then loop through all the rows. Basically the Employees collection is a strongly typed collection object that acts as the placeholder for the Employee objects.
Object Implementation
In this section, we will consider the implementation of the Employee class as well as the Employees class that holds strongly typed Employee objects. We will start our discussion by looking at the implementation of the Employee class.
Employee Class Implementation
First let's create a new Visual C# class library project named ObjectDeclarations and rename the default class from class1 to Employee. As the name suggests, the Employee class holds details of an Employee and exposes the attributes of an employee by means of public properties. Here is the code of the Employee class.
using System;
namespace ObjectDeclarations
{
[Serializable]
public
class Employee
{
private
int _employeeID;
private
string _lastName = "";
private
string _firstName = "";
private
string _title = "";
public
Employee()
{
}
public
int EmployeeID
{
get
{
return
_employeeID;
}
set
{
_employeeID
= value;
}
}
public
string LastName
{
get
{
return
_lastName;
}
set
{
_lastName
= value;
}
}
public
string FirstName
{
get
{
return
_firstName;
}
set
{
_firstName
= value;
}
}
public
string Title
{
get
{
return
_title;
}
set
{
_title
= value;
}
}
}
}
In the above lines of code, we decorate our class with the keyword Serializable to allow our class to be serializable. This attribute makes it possible to convert the UserObject into a linear sequence of bytes for either storage or transmission to another location. Apart from the constructor, we have also declared a number of public get/set properties.
Employees Class Implementation
Now that we have had a look at the Employee class, let us consider the implementation of the Employees class that acts as the placeholder for storing a collection of Employee objects. Here is the code of the Employees class.
using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ObjectDeclarations
{
[Serializable]
[XmlRoot("Employees")]
public
class Employees:IEnumerator, ICollection
{
//Private member variable that holds
the underlying Collection.
private
ArrayList _employeesArray;
//
Private member variable that holds the index of the current //InformationCollection.
private
int _index = -1;
public
Employees()
{
_employeesArray
= new ArrayList();
}
public
Employees(ArrayList theArrayList)
{
_employeesArray
= theArrayList;
}
public
int Count
{
get
{
return
_employeesArray.Count;
}
}
public
void Add(Employee obj)
{
_employeesArray.Add(obj);
}
public
void Remove(Employee obj)
{
_employeesArray.Remove(obj);
}
public
Employee this[int indexer]
{
get
{
//Check
if the indexer falls in allowable range.
if
((indexer >= 0) &&
(indexer
< _employeesArray.Count))
return
(Employee)_employeesArray[indexer];
else
throw
new
System.IndexOutOfRangeException("Index
must
be
between 0 and " +
_employeesArray.Count.ToString()
+ ".");
}
}
public
IEnumerator GetEnumerator()
{
return
(IEnumerator) new Employees(_employeesArray);
}
public
object Current
{
get
{
return
_employeesArray[_index];
}
}
public
bool MoveNext()
{
_index++;
return
_index < _employeesArray.Count;
}
public
void Reset()
{
_index
= -1;
}
public
ArrayList GetArrayList()
{
return
_employeesArray;
}
public
object SyncRoot
{
get{return
this;}
}
public
bool IsSynchronized
{
get{return
false;}
}
public
void CopyTo(Array a, int index)
{
_employeesArray.CopyTo(a,index);
}
}
}
We start by deriving our collection class from IEnumerator and ICollection classes. After that we implement various properties and methods such as Count, IsSynchronized, SyncRoot, Current, MoveNext and Reset that are defined in the ICollection and IEnumerator interfaces.
Implementation of an ASP.NET Application >>