This simple article describes how to pass data between different layers of your application using Generic list collections.
Update:
After going through this article, please read my response below. It's better to use Collection<T> than List<T>.
Introduction
This article is for beginners who want to know how to use .NET generics to pass data between different layers. If you do not know about generic list, please go thorugh this article http://www.dotnetfunda.com/articles/article152.aspx. In brief, List class is a generic equivalent of ArrayList class.
If you want to learn about how to develop 3-tier architecture application, please go through http://www.dotnetfunda.com/articles/article18.aspx and how to develop 4-tier architecture, please go through http://www.dotnetfunda.com/articles/article18.aspx. To show the use of generics, I have used downloadable source code available for 4-Tier architecure article.
There were discussion earlier and probably now also on whether we should use DataTable or generic List collection class to pass data between layers, you can read through http://weblogs.asp.net/bsimser/archive/2007/04/04/datatable-vs-bindinglist-t.aspx post to learn more about that but now I feel its evident that using Generic list to pass data between layers is the way to go. I personally prefer Genericl List over DataTable as I have seen its beneifts working in different projects.
There are different views on where the actual conversion of data from DataTable or DataReader to list should happen, some suggest to have a separate translation layer that accepts DataTable or DataReader and converts them into the list of desired objects. Normally people do it into Data Access Layer itself and pass the generic list objects to Presentation Layer through Business Layer. In this demonstration, I shall do the same.
Ideally, if you have preferred to use generic list to pass data between differenet layers you should prefer using entity layer (or I have called BO - Business Objects layer as described in the 4-Tier architecture application article referenced above). In this example, I have a Person business object / entity object that have properties related to a person, I am trying to fill into generic list.
Below code is the Data Access Layer code that gets data from database and convert them into generic list collection. Please note that I have used latest version of C# (3.0) that supports var keyword and other features I have used in below code snippets.
/// <summary>
/// Load records from the database using DataReader
/// </summary>
/// <returns></returns>
public List<Person> LoadThroughDataReader()
{
var list = new List<Person>();
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand cmd = new SqlCommand("LoadAll", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Person p = new Person()
{
Age = reader.GetInt32(reader.GetOrdinal("Age")),
FirstName = reader.GetString(reader.GetOrdinal("FirstName")),
LastName = reader.GetString(reader.GetOrdinal("LastName"))
};
list.Add(p);
}
}
conn.Close();
}
return list;
}
}
/// <summary>
/// load returns from database using DataTable
/// </summary>
/// <returns></returns>
public List<Person> LoadThroughDataTable()
{
var list = new List<Person>();
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand cmd = new SqlCommand("LoadAll", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
using (SqlDataAdapter ad = new SqlDataAdapter(cmd))
{
DataTable table = new DataTable();
conn.Open(); // open the connection
ad.Fill(table);
conn.Close(); // close the connection
// loop through all rows
foreach (DataRow row in table.Rows)
{
Person p = new Person()
{
Age = int.Parse(row["Age"].ToString()),
FirstName = row["FirstName"].ToString(),
LastName = row["LastName"].ToString()
};
list.Add(p);
}
}
}
return list;
}
}
In the above code snipeet, I have two method called LoadDataThroughDataReader and LoadDataThroughDataTable. In both method, I have declared a variable for List<Person> that is filled with the Person records returned from the database. The first method LoadDataThroughDataReader use cmd.ExecuteReader() method to get the SqlDataReader and read through all the records in the reader and add the Person object into the List. The second method is slightly different and use DataTable instead of DataReader to fetch data from database, loop through all the rows of the DataTable and add Person objects into the list.
You may wonder why these two methods when both are doing the same thing. I prefer using DataReader when I have lesser amount of data from the database and loop through because DataReader expect live connection when it loops through all the records. For large amount of data, it may be a bottleneck for the database to keep the connection alive and loop through. So for large amount of data I prefer to fill the DataTable, close the database connection and then loop through all the records do the required operation.
Once you have your Data Access Layer method ready to return the generic list collection, you can call it through your business layer (My business layer class name is PersonBAL) as follows:
/// <summary>
/// load records through data reader
/// </summary>
/// <returns></returns>
public List<Person> LoadThroughDataReader()
{
return new PersonDAL().LoadThroughDataReader();
}
/// <summary>
/// load records through datatable
/// </summary>
/// <returns></returns>
public List<Person> LoadThroughDataTable()
{
return new PersonDAL().LoadThroughDataTable();
}
Get solutions of .NET problems with video explanations, .pdf and source code in .NET How to's.
As I do not have any logic in the Business Layer, so I have simply instantiated the PersonDAL data access layer object and called the respective methods.
Subsequently, this business layer methods can be called from presentation layer as follows:
GridView g1 = new GridView();
g1.DataSource = new PersonBAL().LoadThroughDataReader();
g1.DataBind();
PlaceHolder1.Controls.Add(g1);
GridView g2 = new GridView();
g2.DataSource = new PersonBAL().LoadThroughDataTable();
g2.DataBind();
// I have a place holder control in the .aspx page in which both above gridview is added
PlaceHolder1.Controls.Add(g2);
As GridView DataSource supports generic list also as data source so we can directly assign the business layer method as the GridView datasource and all the records from the generic list collection will be populated as rows into the GridView. All the properties of the Person object will be treated as the column of the GridView unless you have explictely assigned the columns in the GridView.
Hope you find this article interesting, please subscribe for the subsequent article alert directly in your email box. Happy coding!