UPDATE: Updated article with project structure on 3 tier architecture in ASP.NET here.

3-Tier Architecture in ASP.NET with C#

SheoNarayan
Posted by in ASP.NET category on for Intermediate level | Views : 1876281 red flag
Rating: 4.75 out of 5  
 24 vote(s)

3-Tier architecture is a very well know buzz word in the world of software development whether it web based or desktop based. In this article I am going to show how to design a web application based on 3-tier architecture.


 Download source code for 3-Tier Architecture in ASP.NET with C#

Updated on July 01 2008: Source Code attached

Introduction

3-Tier architecture generally contains UI or Presentation Layer, Business Access Layer (BAL) or Business Logic Layer and Data Access Layer (DAL).

Presentation Layer (UI)
Presentation layer cotains pages like .aspx 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, if needed. I will call it Business Access Layer in my demo.

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). For this demo application, I have taken a very simple example. I am assuming that I have to play with record of persons (FirstName, LastName, Age) and I will refer only these data through out this article.

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
Lets proceed 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. (In my case I have a 3-Tier folder inside App_Code folder, you can directly add inside App_Code or you can create a separate project for DAL and add reference of this project into your BAL.) 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 or you may download attachment from http://www.dotnetfunda.com/articles/article18.aspx article and look for App_Data folder for complete database structure and stored procedure for this article.

Data Access Layer (DAL)

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();
}
}

}

In the above code, I have a member variable called connStr 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) (In my case I have a 3-Tier folder inside App_Code folder, you can directly add inside App_Code or you can create a separate project for BAL and add reference of this project into your Presentation Layer). 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;
}
}

}

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 Age.

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>
Age:
</td>
<td>
<asp:TextBox ID="txtAge" runat="Server" Columns="4"></asp:TextBox>
</td>
<td>
<asp:RequiredFieldValidator ID="req3" runat="Server" Text="*" ControlToValidate="txtAge"
Display="dynamic"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="Comp1" runat="Server" Text="Only integer" ControlToValidate="txtAge"
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 age = Int32.Parse(txtAge.Text);

try
{
intResult = pBAL.Insert(firstName, lastName, age);
if (intResult > 0)
lblMessage.Text = "New record inserted successfully.";
else
lblMessage.Text = "FirstName [<b>"+ txtFirstName.Text +"</b>] alredy exists, try another name";

}
catch (Exception ee)
{
lblMessage.Text = ee.Message.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, age as parameter.

Dispalying Records into GridView



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

Code for GridView

<asp:GridView ID="GridView1" runat="server" CellPadding="4" ForeColor="#333333" GridLines="None"
DataKeyNames="PersonID" AutoGenerateEditButton="True" AutoGenerateColumns="False"
OnRowEditing="EditRecord" OnRowUpdating="UpdateRecord" OnRowCancelingEdit="CancelRecord"
OnRowDeleting="DeleteRecord" PageSize="5" >
<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<RowStyle BackColor="#EFF3FB" />
<EditRowStyle BackColor="#2ff1BF" />
<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
<PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:BoundField DataField="PersonID" HeaderText="Person ID" ReadOnly="True" SortExpression="PersonID" />
<asp:TemplateField HeaderText="First Name" SortExpression="FirstName">
<ItemTemplate>
<%# Eval("FirstName") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtFName" runat="Server" Text='<%# Eval("FirstName") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Last Name" SortExpression="LastName">
<ItemTemplate>
<%# Eval("LastName") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtLName" runat="Server" Text='<%# Eval("LastName") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Age" SortExpression="Age">
<ItemTemplate>
<%# Eval("Age") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtAge" runat="Server" Text='<%# Eval("Age") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete?">
<ItemTemplate>
<span onclick="return confirm('Are you sure to Delete?')">
<asp:LinkButton ID="lnBD" runat="server" Text="Delete" CommandName="Delete"></asp:LinkButton>
</span>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>


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)
{
lblMessage.Text = ee.Message.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);

lblMessage.Text = "Record Deleted Successfully.";
}
catch (Exception ee)
{
lblMessage.Text = ee.Message.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 tAge = (TextBox)row.FindControl("txtAge");

// instantiate BAL
PersonBAL3 pBAL = new PersonBAL3();

try
{
intResult = pBAL.Update(personID, tFN.Text, tLN.Text, int.Parse(tAge.Text));
if (intResult > 0)
lblMessage.Text = "Record Updated Successfully.";
else
lblMessage.Text = "Record couldn't updated";
}
catch (Exception ee)
{
lblMessage.Text = ee.Message.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 p[assing 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.

Hope this article helped you understanding 3-Tier architecture and desiging it.

Thanks and Happy Coding !!!

Updated on July 01 2008: Source Code attached
Page copy protected against web site content infringement by Copyscape

About the Author

SheoNarayan
Full Name: Sheo Narayan
Member Level: HonoraryPlatinum
Member Status: Administrator
Member Since: 7/8/2008 6:32:14 PM
Country: India
Regards, Sheo Narayan http://www.dotnetfunda.com

Ex-Microsoft MVP, Author, Writer, Mentor & architecting applications since year 2001. Connect me on http://www.facebook.com/sheo.narayan | https://twitter.com/sheonarayan | http://www.linkedin.com/in/sheonarayan

Login to vote for this post.

Comments or Responses

Posted by: Raja on: 5/7/2008
This is very nice and simple article.

Keep it up!!!
Posted by: Vansree on: 6/1/2008
Hi,

Nice article; Well and simply explained.

1) Fix for the code block
For the css 'pre',
add new property 'min-width: 730px;' and add width nn percentage. just to give you flexibility to not show scroll bar for long screens.

pre {
...
min-width:730px;
overflow:auto;
...
width:75%; }

2) Can you post other similar article with Ajax?

I wonder if you can come up with the same but using Ajax Tabs. Because the new buzz in the industry is to use Ajax Tab Panels.

Tab Container (Container to hold GV, Add, Edit)

First Tab Panel ... Grid View
Second / on add click: Tab Panel ... Add new record
Last Tab Panel ... Edit Record (and delete button)

Why? Delete button only in edit record? Because in practice we expect the delete to be performed with confirmation and also in details screen. (In most of the projects)

Why? Add new / Edit in 2 different tab panels - to have better usability. Like having add button in Grid View will switch you to Tab Panel (Add new) and then perform the add ...

Mattberseth.com has good UI examples.

But would like to see if you can come up with Tabs and your example above. Just a thought! I liked the way you explained!

Regards,

Sreedhar

Posted by: SheoNarayan on: 6/1/2008
Thanks Vansree for your suggestions.

1. Regarding pre class, I will let the webmaster know about it.
2. As far as article on Ajax is concerned, I will try my best to post few articles on Ajax in coming days.

Thanks and take care.
Regards


Posted by: Hm_sheikh on: 7/16/2008
This is simpler example for 3-Tier Architecture.
I have one question about passing the data between layers.
As you have used four variables to pass data from one layer to another (personID, firstName, lastName, age).
Now think the Scenario when the number of fields are too much. In this case definitely the passing number of variable will not be good idea.
How we can pass a large amount of data from one layer to another.
Please keep the performance issue in the mind.

Regards
Haneef
Posted by: SheoNarayan on: 7/16/2008
Hi Haneef,

In this case use my another article on 4-Tier architecture http://www.dotnetfunda.com/articles/article18.aspx

Thanks
Posted by: Pushpalata on: 8/25/2008
Hi Sir,

IF in Insert method of DAL I have out parameter, how to access it in presentation layer
Posted by: SheoNarayan on: 8/25/2008
Pushpalata,

Read following article to know how to use output parameter

http://www.eggheadcafe.com/PrintSearchContent.asp?LINKID=624

http://asp.dotnetheaven.com/howto/doc/adoplus/OutParams.aspx

Hope this will hep.

Thanks
Posted by: Moloy2008 on: 9/1/2008
Dear Sir,
Thanks so much for such a nice article, I am sure it will help a lot of new .Net learners like me.

I have a small problem while using your code, I am not being able to enter and save a date field in a plain textbox (also tried using a datepicker).

Can you please help me telling me how to capture a date field and save it in SQL 2005. You may also please send me some useful link, if possible.
Posted by: SheoNarayan on: 9/1/2008
Not sure if you are getting any error while saving datetime field into database or some other problem exists.

Please see below links, it might help you.

http://forums.msdn.microsoft.com/en-US/vbgeneral/thread/d5af5335-8c60-4f6a-aa04-8a4fad923485/
http://www.themssforum.com/Ado/Saving-DateTime-120524/
http://forums.asp.net/p/1232201/2228157.aspx
http://www.c-sharpcorner.com/Forums/ShowMessages.aspx?ThreadID=42132

Thanks
Posted by: Moloy2008 on: 9/2/2008
Dear Sir,


I find there is a format mismatch between iBO.HelpDeskCallDate and txtHelpDeskRequestDate in the code-behind but really dont know how to fix it.

I find in my Immediate Window the values iBO.HelpDeskCallDate - {1/1/0001 12:00:00 AM} txtHelpDeskRequestDate : "30-8-2008 16:35:53" I am new to programming, but looking at this I feel IBO.HelpDeskCallDate is expecting the format which is not provided by txtHelpDeskRequestDate... Pl Help...

Posted by: SheoNarayan on: 9/2/2008
The problem you are talking about is related with a specific scenario. May I request you to post it in the Questions section of this website? Hopefully you will get quicker solution.

A little hint in order to solve your problem is "30-8-2008 16:35:53" is not a correct DateTime format (try to convert or parse it to DateTime and you will get error). So just pass the value in correct DateTime format.

Thanks
Posted by: Tulsim83 on: 9/8/2008
Hi,

I have a question about the list.aspx page. Just curious why you did not use the gridview wizard to display the list of records. So for example, configure a sqldatasource and then bind it to the grid view control. Wouldn't this be easier? What are the pros/cons of this approach?

Thanks.
tulsi
Posted by: SheoNarayan on: 9/8/2008
When you will use SqlDataSource, you are writing your select query, connectionstring and other stuffs at the page itself. This approach is good if you have a small project but for bigger projects it is not suggestable. For further you can refer to this page

http://www.willasrari.com/blog/usefulness-of-sqldatasource/000193.aspx


Thanks
Posted by: Tulsim83 on: 9/9/2008
Thanks for the feedback. This is exacly the info I was looking for.

Also, thanks for posting such a nice article.

Tulsi
Posted by: Tulsim83 on: 9/10/2008
One more question....

Did you create the source code for the list.aspx page manually or did you use some type of wizard to do this?

I'm use to binding the gridview to the sqldatasource, but want to learn more on the way you created this page. Are there any good tutorials for this?

Thanks again.
tulsi
Posted by: SheoNarayan on: 9/11/2008
For columns I wrote the code myself and for styles of HeaderTemplate, FooterTemplate etc. I used the template available for the GridView via Smart menu in VS.
Posted by: Nazirk on: 2/26/2009
Hi SheoNarayan,

Indeed a very useful article with easy to understand example.
But SheoNarayan, as in this example you are creating DAL and BAL inside App_Code, I need an architecture wherein the DAL and BAL should be outside App_Code folder.
Because I am trying to implement this but not getting it.
The folder structure what i am looking for the 3 layers should be like this;

--PRESENTATION LAYER --- (this is the startup project)
--APP_CODE
--APP_DATA
--Default.aspx
--Home.aspx
--Web.config
--DAL
--clsEmployees
--clsTransport
--BAL
--clsLoad
--clsGetEmployees

this is what i need to implement. Can you plz help me out!!!

thanks & regards
nazir k

Posted by: SheoNarayan on: 2/26/2009
Nazirk,

You need to use Visual Studio to create BAL and DAL as separate projects. Once you have created BAL, DAL as separate proejcts, you can right click the solution and Add Reference to those projects in your web application.

You can create a blank Solution, Add a Web application. Add projects (BAL, DAL) into the same solution and implement the code as it is in the App_Code folders.

Hope this will give little idea.

Thanks
Posted by: chiragpshah87-3857 on: 3/13/2010
Hi, this is very good code and its very useful,
other thing is that its not giving any error after copy the code, for that thank you very much.
thanks
Posted by: DON090111982 on: 9/1/2010 | Points: 10
protected void SortRecords(object sender, GridViewSortEventArgs e)
{
DataTable dataTable = GridDataSource();

if (dataTable != null)
{
DataView dataView = new DataView(dataTable);

dataView.Sort = GetSortExpression(e);

GridView1.DataSource = dataView;
GridView1.DataBind();
}
}
#region Private Methods

/// <summary>
/// Bind the gridview
/// </summary>
private void BindGrid()
{
GridView1.DataSource = GridDataSource();
GridView1.DataBind();
}

/// <summary>
/// Get GridView DataSource
/// </summary>
private DataTable GridDataSource()
{
PersonBAL3 p = new PersonBAL3();
DataTable dTable = new DataTable();
try
{
dTable = p.Load();
}
catch (Exception ee)
{
lblMessage.Text = ee.Message.ToString();
}
finally
{
p = null;
}

return dTable;
}

/// <summary>
/// Get sort expression for the gridview
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
private string GetSortExpression(GridViewSortEventArgs e)
{
string sortDirection = string.Empty;
// if clicked on the same column twice then let it toggle the sort order, else reset to ascending
if (ViewState["SortExpression"] != null)
{
if (!ViewState["SortExpression"].ToString().Equals(e.SortExpression.ToLower()))
{
ViewState["SortDirection"] = null;
}
}

if (ViewState["SortDirection"] != null)
{
if (ViewState["SortDirection"].ToString().Equals("ASC"))
{
sortDirection = "DESC";
ViewState["SortDirection"] = "DESC";
}
else
{
sortDirection = "ASC";
ViewState["SortDirection"] = "ASC";
}
}
else
{
ViewState["SortDirection"] = "ASC";
}
ViewState["SortExpression"] = e.SortExpression.ToLower();

return e.SortExpression + " " + sortDirection;
}
#endregion Private Methods
Posted by: DON090111982 on: 9/1/2010 | Points: 10
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 tAge = (TextBox)row.FindControl("txtAge");

// instantiate BAL
PersonBAL3 pBAL = new PersonBAL3();

try
{
intResult = pBAL.Update(personID, tFN.Text, tLN.Text, int.Parse(tAge.Text));
if (intResult > 0)
lblMessage.Text = "Record Updated Successfully.";
else
lblMessage.Text = "Record couldn't updated";
}
catch (Exception ee)
{
lblMessage.Text = ee.Message.ToString();
}
finally
{
pBAL = null;
}

GridView1.EditIndex = -1;
// Refresh the list
BindGrid();
}

/// <summary>
/// fires when Delete button is clicked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);

lblMessage.Text = "Record Deleted Successfully.";
}
catch (Exception ee)
{
lblMessage.Text = ee.Message.ToString();
}
finally
{
pBAL = null;
}

GridView1.EditIndex = -1;
// Refresh the list
BindGrid();
}

/// <summary>
/// Fires when page links are clicked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void ChangePage(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
// Refresh the list
BindGrid();
}
Posted by: DON090111982 on: 9/1/2010 | Points: 10
public partial class UserLogin : System.Web.UI.Page
{
string strLoginError = string.Empty;

#region Private Methods
private bool IsValideUser(string userName)
{
UserBAL objUserBAL = new UserBAL();
DataTable dt=new DataTable();
try
{
dt = objUserBAL.IsValideUser(userName);
if (dt.Rows.Count == 0)
{
strLoginError = "Invalid User Name";
dt.Dispose();
return false;
}
else
{
string strTempPassword = Convert.ToString(dt.Rows[0]["password"]).Trim();
if (strTempPassword != Login1.Password.Trim())
{
strLoginError = "Invalid Password";
dt.Dispose();
return false;
}
return true;
}
}
catch (Exception e)
{
lblMessage.Text = e.Message.ToString();
return false;
}
}
#endregion

#region Protected Methods
protected void Page_Load(object sender, EventArgs e)
{

}
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
if (IsValideUser(Login1.UserName.Trim()))
{
e.Authenticated = true;
}
else
{
e.Authenticated = false;
}
}
protected void Login1_LoginError(object sender, EventArgs e)
{
Login1.FailureText = strLoginError;

}
#endregion
}
Posted by: DON090111982 on: 9/1/2010 | Points: 10
tblUserMaster,uniq key,tblAdminMaster,tblUserLoginMaster,tblUserLoginDetails
spValidateUser,spCreateUser,spLoginUser
Posted by: Sushant_rajurkar on: 9/9/2010 | Points: 10
hi sir,
i kindly request you to please explain in detail whatever you haven't explained in your tutorial. i actually want you to explain how to connect to database and manipulate the data.
i have confusion about your sentence below. what else is left about connecting database.
" I am not goint into details of how I am connecting database and manipulating the data just
to make this tutorials short."



Posted by: Sushant_rajurkar on: 9/10/2010 | Points: 10
hi sir,
sorry for silly quetion but, if same methods written in data access layer and business logic layer then what is use of business logic layer plz clarify in detail.

Posted by: Rams73 on: 11/6/2010 | Points: 25
Hi sir,
if i am writing the logic you are used in business layer within default.aspx.cs then, we can sayl that default.aspx.cs page as business layer.
Posted by: Fscopel on: 12/14/2010 | Points: 25
Sheo Narayan,
Nice tutorial. you kept it simple and straight forward.
I do have to disagree, with part of your code. In your code the BAL is simply there to call the DAL. It is irrelevant as is. In your UI if you (CTRl + H) substitute PersonBAL3 for PersonDAL3 it will work the same way. I think to make your code A++ you need to add some validation to the BAL to make it relevant. Besides that great job.

Thank you for your post.


Posted by: SheoNarayan on: 9/4/2011 | Points: 25
@Fscopel,

Thank you for appreciating it and response. I agree that as there is no validations in the BAL, we can directly call the DAL from the UI, however I have mentioned this in the "Business Access Layer" first paragraph that "As we don't have any business logic here so simply instantiate the PersonDAL3 class of DAL and call methods. " . As this being a article, I wanted to make the code snippet a real simple and easy to understand so I just kept it direct ;).

However your point is valid, in read scenario if required we need to keep the business validations in the business access layer.

Thanks again for your feedback, keep participating and sharing your knowledge.

Regards
Sheo Narayan
Posted by: Vineesh on: 2/4/2011 | Points: 25
Hi sir

Thanks for this informative article..

could u please tell me how can I implement sql transaction in this code to ensure ACID

regards...
vineesh
Posted by: Senthilk on: 2/5/2011 | Points: 25
Hi Narayan,

Thanks for the nice article. One question regarding the deployment of 3-tier application.

I feel the sample given by you cannot be deployed straightaway in 3 different servers. Is it right? If I want to develop such a 3-tier application, how should I do? Can you please explain that in detail in an article?

Regards,
Senthil Kumar K


Posted by: Patelpriyanka21 on: 2/15/2011 | Points: 25
Hello Sir,
i am new in .net and when i am implementing this article then getting bal error in default form.error is the type of namespace 'persobBal3' could not be found (are you missing a using directive or an assembly reference?) and other error are for text box like the name 'textfirstbox' does not exist in current context.
so pls guide me how to solve this.

Thankx
Posted by: Vanchi050585 on: 3/23/2011 | Points: 25
Dear Sir,

Nice this article is very usefull to me.

but one clarifications in that. if i insert the same thing again means, the error message was displayed in lblmessage box like below:
Violation of PRIMARY KEY constraint 'PK_tblClassifieds'. Cannot insert duplicate key in object 'dbo.tblClassifieds'. The statement has been terminated.

but i want to displayed like:
Title Business oppurtunity already exists, try another name

how to calculate the intResult column , how to design datatype in Table Design.
please let me about the Table Design

thanks in Advance
Posted by: Titochhabra on: 11/11/2011 | Points: 25
This is awesome!! really helpful for me. Thanks for sharing with us. This link
http://mindstick.com/Blog/264/LINQ%20Implementation%20on%203%20tier%20application
also helped me to complete my task.

Thanks Everyone!!
Posted by: Nandu on: 2/10/2012 | Points: 25
Hi sir,

Thanks for the nice article, but when i am implementing this application am getting error like The name 'dTable' does not exist in the current context... give me the solution.

Thanks,
Posted by: Jmckamal on: 3/27/2012 | Points: 25
Please explain me.. why we need business layer here? If we can able to achieve this without business layer then why is it required?.
Posted by: Jmckamal on: 3/27/2012 | Points: 25
The reason I am asking is.. I have done the same without of business layer. Then I myself asking everytime.. why I need this?
Posted by: Go2sumit on: 5/25/2012 | Points: 25
Please do help... i used your code available in BAL, DAL and defult.aspx for insertion only.But i am getting an error on label i.e. instance failure.
Kindly suggest what to do now ?? please.
Posted by: Eangland1234 on: 6/8/2012 | Points: 25
to Hm_sheikh
if you have much data to pass you can user Model to pass data
nomally we user model to pass
Posted by: Devashishjangid831989 on: 6/10/2012 | Points: 25
Nice Artical,thnx 4 it....
Posted by: Britsouls on: 6/19/2012 | Points: 25
Dear sir,
This was the best answer i could expect.
thank you for making it such simple to be understood by everybody.


Posted by: Anishabathija on: 10/10/2012 | Points: 25
hi sir,
great article.
I had a doubt. In my application in the gridview I have a dropdownlist displaying two options yes or no.
I added this using the
<Asp:tempalatefield>
<asp:itemlist>
<asp:dropdownlist>
<asp:ListItem>yes</asp:ListItem>
<asp:listitem>no</asp:listitem>///

and in my rowupdating event of the gridview I passed this as
string option = Convert.ToString((GrdView1.Rows[e.RowIndex].Cells[5].Controls[0]).ToString());


this code built succesfully
but everytime I run it and try to update the dropdownlist , it gets updated as Sytem.Web.Controls in the db.
please help.
any help will be appreciated. :)

Posted by: Dinoop.Uk on: 10/12/2012 | Points: 25
Hi sir

Nice article.
I have a doubt here is it good practice to pass values between layers by parameters?Using a separate Class(Helper class) may be a better option.
Please comment on this

Thanks in advance

Dinoop

Posted by: Munder2013 on: 5/19/2013 | Points: 25
Vry useful article
thanks for sharing

Posted by: t5j9033387989 on: 9/12/2013 | Points: 25
this is the most useful article thanks..it is so helpful. for begineers. to learn about 3 tier architecture.

Posted by: Raja on: 9/27/2013 | Points: 25
Awesome Sheo,

Good effort in explaining this.

Thanks
Posted by: Gurumatrix2004 on: 6/13/2014 | Points: 25
Very useful article...especially for fresher who want to understand 3 tier implementation in their projects...Thanks
Posted by: Noozdahmag on: 12/26/2019 | Points: 25
very useful article,browse https://www.19kala.com/mag/

Login to post response

Comment using Facebook(Author doesn't get notification)