Building a 3-tier Architecture Using the ObjectDataSource in ASP.NET 2.0

Mar 3, 01:37 pm

Introduction

Now it is possible to have a 3 - tier architecture in ASP.NET 2.0 using data source controls. For this purpose the ObjectDataSource control was introduced in ASP.NET 2.0. This data source, uniquely of the available controls, involves a user-defined class, which means you can write your own custom methods to select, insert, update and delete data from the database. In order to build large scale applications, reusability and data encapsulation are major concerns and the ObjectDataSource control, with its support for custom code, can play a very useful role here.

Lets first quickly review what a 3-tier architecture is. As the name suggests, 3-tier architecture is divided into 3 layers as given below:

  1. The Presentation tier
  2. The Business Logic tier
  3. The Data tier

The presentation tier supplies the user interface on a client machine. The business logic tier contains functional process logic. The data tier, an RDBMS (relational database management system) on a database server contains the data storage logic.

The 3-tier architecture has many advantages over other architectures, some of them are listed below:

  1. Separation of the presentation logic
  2. Easier to modify one tier without affecting the other tiers
  3. Effective network performance
  4. Three tier applications are easy to maintain and provides reusability and scalability

You can separate out the presentation tier, business tier and database tier by using the ObjectDataSource Control. The Presentation tier typically contains a web site (UI). The Business tier contains the classes that implements business rules, validations, etc. The third tier that is the Database tier contains the database that contains data for the application. The SQL statements that do the database access should be saved as stored procedures within the database, but the SQL statements are often stored in data access class. Previous versions of ASP.NET couldn't support business tier customization using data source controls directly.

Figure 1 shows a typical 3-tier architecture using the ObjectDataSource.

Figure 1. Three-tier architecture using ObjectDataSource

As I hinted earlier, the ObjectDataSource gets its data through a custom data access class that handles the operations related to database access. This is specified by a TypeName property that specifies a name of business object class, and contrasts with, for example, SqlDataSource which uses the ConnectionString property to control access to the datasource. . To perform CRUD (create, read, update, delete) operations, a minimum of four functions are required - functions for selecting records from a database (SelectMethod()), inserting records (InsertMethod()), updating records (UpdateMethod()) and deleting records (DeleteMethod()).

If you use the ObjectDataSource to only display records in a GridView, it will call the associated function SelectMethod() that is present in the data access class to obtain the data to be displayed in the GridView. The ObjectDataSource control can be used with any data-bound controls in ASP.NET 2.0. The control's SelectMethod() (i.e. Function associated in data access class) must return a DataSet, Typed DataSet, IEnumerable implementation, Collection, or an Array.

Insert, update, delete methods that are present in the data access class must take each field either as individual parameters, or as a single object containing the fields as properties. The ObjectDataSource control uses the new .NET reflection feature to determine the parameters that are expected by the data access class. The .NET reflection feature provides information about the complied class at runtime. It determines what methods are provided by a particular class, what parameters each method requires and also the types returned by the method. The ObjectDataSource control has one more property named as DataObjectTypeName, where the value of this property is the associated class name. Exception handling can be done inside the functions of the business object class. Various business rules can be set using the control's defined functions. It is also possible to create a custom exception class to raise validation errors through the ObjectDataSource control's ObjectDataSource_Updated Event. You can also use ObjectDataSource_Updating, ObjectDataSource_Inserting, ObjectDataSource_Inserted, ObjectDataSource_Deleting, ObjectDataSource_Deleted events to handle the exceptions.

When the ObjectDataSource control is used with bound-controls like GridView, DetailsView, FormView property names must match with DataField properties of the BoundField elements for each bound column in bound control that is used in select, insert, update and delete operations.

System Requirements

In order to run the sample code you should have the following:

  • A web server running Windows 2000, XP or 2003
  • Microsoft Visual Studio .NET 2005 / Web Developer Express Edition (.NET Framework version 2.0)
  • Microsoft Internet Explorer 5.5 or higher

Installing and Compiling the Sample Code

The sample download for this article contains a VS 2005 Website project named EmployeeObjectDataSource.

To install the sample:

1. Unzip the sample code zip file to a new folder on your webserver

2. In VS 2005 from the top menu, select File → Open Website

3. Select the folder you unzipped the download to and you will be able to run the sample

ObjectDataSource Overview

To start using the ObjectDataSource control, drag the control from Data toolbox onto the design view of a page. The following table provides some of the more common attributes of the ObjectDataSource control:

AttributeDescription
IDThe ID of the control.
TypeNameName of the data access class that is marked with the DataObject attribute.
DataObjectTypeName of the class that specifies the type that is passed to the insert/update/delete methods
ConflictDetectionConcurrency checking technique. You can set this to either CompareAllValues or OverwriteChanges for this property.
SelectMethodUsed to get/set the name of the function used to retrieve data.
InsertMethodUsed to get/set the name of the function used to insert data.
UpdateMethodUsed to get/set the name of the function used to update data.
DeleteMethodUsed to get/set the name of the function used to delete data.

The ObjectDataSource control does not support visual design features such as the EnableTheming or SkinID property used on other controls. There is no visual presence of the control on web page.

Conflict Detection

In the case of multi-user applications, if one user is editing the record while another user updates the same record there is the potential for a conflict, as by default only the last update will be saved to the database. By setting the ConflictDetection property to CompareAllValues, conflicts can be avoided - in this case, both old and new values are submitted as a parameter to the update method. The original values can then be included in checks for optimistic concurrency. To work with original values, an original_datafield parameter is generated for each bound field column when you call the update() method. In the case of delete, the method parameter passed is always original_datafield. You can control the names used for the original value parameters by setting the OldValueParameterFormatString property. The default is original_{0} if optimistic concurrency is enabled. It is a good practice to check the concurrency in real world web applications.

Events

The ObjectDataSource control provides a solid event driven model. Following are some of the useful events of the ObjectDataSource control.

  • Selecting
  • Selected
  • Inserting
  • Inserted
  • Updating
  • Updated
  • Deleting
  • Deleted

The Selecting, Inserting, Updating and Deleting events of the ObjectDataSource supply an ObjectDataSourceMethodEventArgs object; this contains an IDictionary collection of parameters that is accessed by the InputParameters property. By using this object you can validate and change the values of the parameters. For example, you can cancel the deletion of a record by setting the Cancel property of the ObjectDataSourceMethodEventArgs to true. On the other hand, the Selected, Inserted, Updated and Deleted events of ObjectDataSource are useful to determine the output parameters, return values and exceptions. The ObjectDataSourceStatusEventArgs object exposes output parameters.

Configuration using Visual Studio 2005

To configure the CRUD methods, in the Visual Studio 2005 design view just hover the mouse on ObjectDataSource control, click for the Smart tag. To configure the control select the Configure Data Source link. The configuration wizard for the control will appear on the screen. The first step in the wizard is to select the business object for the control. Then click the Next button. Now there are four tabs available for configuring the select, insert, update and delete methods. Each tab is used to specify the associated function in the data access class. By default the functions marked with DataObjectMethod attribute will be listed in a dropdownlist so they can easily be selected.

Suppose one of the functions in your data access class requires a parameter, for example suppose my function marked with the DataObjectMethod attribute requires an ID to be passed to it. The wizard provides a Define Parameters step for just this purpose. In this step, select the source of each parameter required.

The Sample Web Application

The sample application uses a Microsoft Access database table named Employee. I'll start by showing you how to use the ObjectDataSource control with the Employee table using a middle-tier business class. Then I'll explain how to perform CRUD operations using the control. So for the rest of the article my approach is totally practical and code-oriented.

Figure 2 shows an example of the web application that will be developed throughout the rest of the article.

Figure 2. The employee table web page from the sample application

Database Design

As I mentioned above, the sample application uses an MS Access database with a single table named Employee. The table layout can be seen in the table below.

Field NameData TypeDescription
EmpIdAuto incrementPrimary Key
FirstNameTextFirst name of the employee
MiddleNameTextMiddle name of the employee
LastNameTextLast name of the employee
EmpCategoryTextType of employee (staff, worker, management)
DesignationTextDesignation of the employee

Business Class for the Employee Table

I will start by first creating a data access class for the Employee table. This class only contains get/set properties for the fields in the table.

Imports Microsoft.VisualBasic
Public Class Employee
    Private lngEmpId As Long
    Private strFirstName As String
    Private strMiddleName As String
    Private strLastName As String
    Private strEmpCategory As String
    Private strDesignation As String
    Public Sub New()
    End Sub
    Public Property EmpId() As Long
        Get
            Return lngEmpId
        End Get
        Set(ByVal value As Long)
            lngEmpId = value
        End Set
    End Property
    Public Property FirstName() As String
        Get
            Return strFirstName
        End Get
        Set(ByVal value As String)
            strFirstName = value
        End Set
    End Property
    Public Property MiddleName() As String
        Get
            Return strMiddleName
        End Get
        Set(ByVal value As String)
            strMiddleName = value
        End Set
    End Property
    Public Property LastName() As String
        Get
            Return strLastName
        End Get
        Set(ByVal value As String)
            strLastName = value
        End Set
    End Property
    Public Property EmpCategory() As String
        Get
            Return strEmpCategory
        End Get
        Set(ByVal value As String)
            strEmpCategory = value
        End Set
    End Property
    Public Property Designation() As String
        Get
            Return strDesignation
        End Get
        Set(ByVal value As String)
            strDesignation = value
        End Set
    End Property
End Class

As can be seen in the code above the property name must match the data field names of the bound field elements that define each bound column. The class also should have a parameterless constructor as shown with the New() method.

This class is then assigned to the ObjectDataSource control's DataObjectTypeName property. You don't need to manually set this property after completion of the configuration wizard. as it is automatically assigned by VS 2005 from the methods marked with the DataObjectMethod attribute. In my case it is an Employee class.

Middle Tier Business Class for the Employee Table

To specify a TypeName for the ObjectDataSource control, one more business class are required that will deal with data. In this class, the methods that are used to select, insert update and delete data are present. The previous Employee class allows you to specify a type that has a property for each data field. Then, instead of passing several parameters to the method, one object is passed and it sets all the properties. This class is a middle-tier class in a 3-tier architecture. A data access tier component encapsulates the ADO.NET code to query and modify the database through SQL commands. So let's take a look at the main data access class for the ObjectDataSource control.

Imports Microsoft.VisualBasic
Imports System.Data
Imports System.Data.OleDb
Imports System.ComponentModel
Imports System.Collections.Generic

Besides some default namespaces, I've also added System.ComponentModel and System.Collections.Generic.

The System.ComponentModel namespace is used to mark methods with attributes in business class for identification purpose. The DataObject and DataObjectMethod attributes are used that follow under System.ComponentModel namespace.

  • <DataObject (True)> - Used to Identify a data object class.
  • <DataObjectMethod(DataObjectMethodType.Select)> - Use this attribute for marking the Select method. This method will appear in the configuration wizard under the Select tab.
  • <DataObjectMethod(DataObjectMethodType.Insert)> - Use this attribute for marking Insert method. This method will appear in the configuration wizard under the Insert tab.
  • <DataObjectMethod(DataObjectMethodType.Update)> - Use this attribute for marking the Update method. This method will appear in the configuration wizard under the Update tab.
  • <DataObjectMethod(DataObjectMethodType.Delete)> - Use this attribute for marking the Delete method. This method will appear in the configuration wizard under the Delete tab.

Generics is a new feature in the .NET Framework 2.0 that provides for a strongly typed collection that can hold only objects of a certain type. If you declare the type of object as integer, then the collection can hold only integer objects. In the sample web application, a list of Employee types is used so this list can hold only Employee objects. To learn more about generics in .NET 2.0 refer to the Related Links section.

I added the System.Collections.Generic namespace because the Select() method return type is a generic list of Employee class objects.

<DataObject(True)> _
Public Class EmployeeTbl
  <DataObjectMethod(DataObjectMethodType.Select)> _
  Public Shared Function GetEmployees() As List(Of Employee)
    Dim sql As String = "SELECT EmpId, FirstName, MiddleName, LastName,
      EmpCategory, Designation " _
      & "FROM Employee"
    Dim cmd As OleDbCommand = _
    New OleDbCommand(sql, New OleDbConnection(GetConnectionString))
      cmd.Connection.Open()
    Dim dr As OleDbDataReader = _
      cmd.ExecuteReader(CommandBehavior.CloseConnection)
    Dim Employees As New List(Of Employee)
    Do While dr.Read
      Dim objEmployee As Employee = New Employee
      objEmployee.EmpId = CType(dr("EmpId"), Long)
      objEmployee.FirstName = dr("FirstName").ToString
      objEmployee.MiddleName = dr("MiddleName").ToString
      objEmployee.LastName = dr("LastName").ToString
      objEmployee.EmpCategory = dr("EmpCategory").ToString
      objEmployee.Designation = dr("Designation").ToString
      Employees.Add(objEmployee)
    Loop
    dr.Close()
    Return Employees
  End Function

The GetEmployees(), GetEmployeesByCategory() and GetEmpCategory() functions return a generic list of Employee objects. In this case the Select() method has the requirement to only retrieve employees related to specific category. The category name will be used as a parameter in the select method and based on that parameter the where condition can be inserted into the SQL that is generated.

This is also possible using the ObjectDataSource control. The GetEmployeesByCategory() method has a strEmpCategory parameter and only returns employees that are belong to specified category. The ObjectDataSource collects information about these parameters in the Define Parameters step of configuration wizard. This step with respect to the GetEmployeesByCategory() method is explained further in the article.

<DataObjectMethod(DataObjectMethodType.Insert)> _
  Public Shared Sub InsertEmployee(ByVal Employee As Employee)
    Dim sql As String = "INSERT INTO Employee " _
      & "(FirstName, MiddleName, LastName, EmpCategory, Designation) " _
      & "VALUES('" & Employee.FirstName & "','" & Employee.MiddleName 
      & "','" & Employee.LastName & "','" & Employee.EmpCategory & "','"
      & Employee.Designation & "')"
    Dim cmd As OleDbCommand = _
    New OleDbCommand(sql, New OleDbConnection(GetConnectionString))
    cmd.Connection.Open()
    cmd.ExecuteNonQuery()
    cmd.Connection.Close()
  End Sub

For the Insert() method, the Employee object is passed as a parameter. By accessing the Employee object's properties, I am going to store values of first name, middle name, last name, employee category and designation in the database. In the web page I've used a FormView control that is bound to a ObjectDataSource control, whenever any record is inserted using the FormView, the ObjectDataSource control's Insert() method will be called which adds the record in the FormView to the Employee table by accessing Employee class's properties. Instead of using a DetailsView I've used a new FormView control that offers greater functionality in working with templates. You can do more customization using a FormView control (i.e. greater flexibility in controlling how the data is displayed) but the part related to ObjectDataSource control will remain same.

<DataObjectMethod(DataObjectMethodType.Update)> _
  Public Shared Function UpdateEmployee(ByVal Employee As Employee, _
    ByVal original_Employee As Employee) As Integer
    Dim sql As String = "UPDATE Employee " _
      & "SET FirstName ='" & Employee.FirstName & "'," _
      & "MiddleName ='" & Employee.MiddleName & "'," _
      & "LastName ='" & Employee.LastName & "'," _
      & "EmpCategory ='" & Employee.EmpCategory & "'," _
      & "Designation ='" & Employee.Designation & "' WHERE EmpId =" 
      & original_Employee.EmpId & " AND FirstName='" 
      & original_Employee.FirstName & "'" & " AND MiddleName='" 
      & original_Employee.MiddleName & "'" & " AND LastName='" 
      & original_Employee.LastName & "'" & " AND EmpCategory='" 
      & original_Employee.EmpCategory & "'" & " AND Designation='" 
      & original_Employee.Designation & "'"
    Dim cmd As OleDbCommand = _
      New OleDbCommand(sql, New OleDbConnection(GetConnectionString))
      cmd.Connection.Open()
    Dim i As Integer = cmd.ExecuteNonQuery()
      cmd.Connection.Close()
    Return i
  End Function

Here in the Update() method, which uses the Employee object, I've also passed an original_Employee parameter, which retains the original values for the employee and is used for the concurrency check. Previously I talked a bit about conflict detection specific to the ObjectDataSource control - this is the implementation. The Update() method is passed two parameters, the first, ByVal Employee As Employee contains the data to be updated and the second, ByVal original_Employee As Employee contains the original data. The Update() method returns a count of the number records that were affected by the update.

<DataObjectMethod(DataObjectMethodType.Delete)> _
  Public Shared Function DeleteEmployee(ByVal Employee As Employee) _
    As Integer
    Dim sql As String = "DELETE FROM Employee " _
      & "WHERE EmpId =" & Employee.EmpId
    Dim cmd As OleDbCommand = _
    New OleDbCommand(sql, New OleDbConnection(GetConnectionString))
    cmd.Connection.Open()
    Dim i As Integer = cmd.ExecuteNonQuery()
    cmd.Connection.Close()
    Return i
  End Function

To delete a record from the Employee table, the DeleteEmployee() method is used by the ObjectDataSource control. The parameter passed to the DeleteEmployee() method is always the original_datafield parameter. The DeleteEmployee() method returns the count of the number of records deleted.

Private Shared Function GetConnectionString() As String
  Return ConfigurationManager.ConnectionStrings _
    ("EmployeeConnection").ConnectionString
End Function

The GetConnectionString() function uses the connection string stored in the new connectionStrings section of the web.config file. In the sample the connectionStrings section contains an add section with name equal to EmployeeConnection. Following is the connectionStrings section for the sample application:

.

<connectionStrings>
  <add name="EmployeeConnection" 
    connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data  
      Source=|DataDirectory|Sample.mdb"
      providerName="System.Data.OleDb" />
</connectionStrings>

In the business object class I've created only one method for each CRUD operation. But it is possible to create multiple methods for different purposes. A business object class can declare public methods that select, insert, update and delete data. These methods can be instance methods or shared methods as I used in the sample application. In the case of instance methods, the ObjectDataSource control will create an instance of the data access class before it calls the method. Creating and destroying a data access object is a time consuming process. That's why I chose to use shared methods. The ObjectDataSource control will not have to create an instance of the data access class when it calls one of the data access methods.

From a caching perspective it is better to use a DataSet as a return type for the Select() method. The ObjectDataSource can cache the data in this case. If the return type for ObjectDataSource is using caching and is not a DataSet or DataTable, then a NotSupportedException will be thrown.

Next, I'll show you how to configure the ObjectDataSource control on your own web page using the wizard.

Start by opening the Default.aspx web page in design view. Just drag and drop a ObjectDataSource control onto the page. Using the control's smarttag, click on the Configure Data Source link. Figure 3 shows the initial step.

Figure 3. Configuring the ObjectDataSource, step 1

Here you just need to specify the data access class name. In this case it is the EmployeeTbl class. Note the Employee class is not present in the list because it is not marked with the DataObject attribute. Next, click on the Next button. The wizard's next step is to assign a method for select, insert, update and delete functions which are present in selected data access class. Click on each tab and select the appropriate method. Only methods marked with the DataObjectMethod attribute will appear in the list. Based on the attributes marked in the business class, the methods are automatically populated in the corresponding tabs within the configuration wizard under the Choose a method dropdownlist. Figure 4 provides an example of the second step in the configuration.

Figure 4. Configuring the ObjectDataSource, step 2

After selecting an associated function for each tab in the wizard click the Finish button. Now take a look at the code added for the ObjectDataSource in page source view. The ObjectDataSource control's properties TypeName, DataObjectTypeName, SelectMethod, InsertMethod, DeleteMethod and UpdateMethod are now set:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
  TypeName="EmployeeTbl"  DataObjectTypeName="Employee" 
  SelectMethod="GetEmployees" 
  InsertMethod="InsertEmployee" 
  DeleteMethod="DeleteEmployee"
  UpdateMethod="UpdateEmployee" 
  OldValuesParameterFormatString="original_{0}"  
  ConflictDetection="CompareAllValues" >
  <UpdateParameters>
    <asp:Parameter Name="Employee" Type="Object" />
    <asp:Parameter Name="original_Employee" Type="Object" />
  </UpdateParameters>
</asp:ObjectDataSource>

Now drag a GridView control to the web page. Set the DataSourceID property to ObjectDataSource1. Configure the GridView fields, the BoundField element's DataField property name must match with the property names in the Employee class. The GridView is used to perform the select, update and delete operations. Let's take a look at GridView code:

<asp:GridView ID="GridView1" runat="server" 
  DataSourceID="ObjectDataSource1"
  AutoGenerateColumns="False" DataKeyNames="EmpId" >
  <Columns>
    <asp:BoundField DataField="EmpId" HeaderText="EmpId" ReadOnly="True" 
      SortExpression="EmpId">
    <ItemStyle Width="15px" />
    </asp:BoundField>
    <asp:BoundField DataField="FirstName" HeaderText="First Name" 
      SortExpression="FirstName">
      <ItemStyle Width="80px" />
    </asp:BoundField>
    <asp:BoundField DataField="MiddleName" HeaderText="Middle Name" 
      SortExpression="MiddleName">
      <ItemStyle Width="80px" />
    </asp:BoundField>
    <asp:BoundField DataField="LastName" HeaderText="Last Name" 
      SortExpression="LastName"> 
      <ItemStyle Width="80px" />
    </asp:BoundField>
    <asp:BoundField DataField="EmpCategory" HeaderText="Employee Category" 
      SortExpression="EmpCategory">
      <ItemStyle Width="50px" />
    </asp:BoundField>
    <asp:BoundField DataField="Designation" HeaderText="Designation" 
      SortExpression="Designation">
      <ItemStyle Width="50px" />
    </asp:BoundField>
    <asp:CommandField ButtonType="Button" ShowEditButton="True" />
    <asp:CommandField ButtonType="Button" ShowDeleteButton="True" />
  </Columns>
</asp:GridView>

To insert a record in the database, drag a FormView control onto the web page. Set the DataSourceID property to ObjectDataSource1. Next set the DefaultMode to Insert for the FormView. The BoundField element's DataField property name must match with the property names in the class. Let's take a look at FormView code:

<asp:FormView ID="FormView1" runat="server" DataSourceID="ObjectDataSource1"
  DefaultMode="Insert" Height="160px" Width="416px">
  <InsertItemTemplate>
    <table>
      <tr>
        <td style="width: 238px">
          First Name:</td>
        <td style="width: 325px">
          <asp:TextBox ID="FirstNameTextBox" runat="server" Text='<%# 
            Bind("FirstName") %>' Width="248px"></asp:TextBox>
        </td>
      </tr>
      <tr>
        <td style="width: 238px">
          Middle Name:
        </td>
        <td style="width: 325px">
          <asp:TextBox ID="MiddleNameTextBox" runat="server" Text='<%# 
            Bind("MiddleName") %>' Width="249px"></asp:TextBox>
        </td>
      </tr>
      <tr>
        <td style="width: 238px">
          Last Name:</td>
        <td style="width: 325px">
          <asp:TextBox ID="LastNameTextBox" runat="server" Text='<%# 
            Bind("LastName") %>' Width="248px"></asp:TextBox>
        </td>
      </tr>
      <tr>
        <td style="width: 238px">
          Employee Category:</td>
        <td style="width: 325px">
          <asp:TextBox ID="EmpCategoryTextBox" runat="server" Text='<%# 
            Bind("EmpCategory") %>'></asp:TextBox>
        </td>
      </tr>
      <tr>
        <td style="width: 238px">
          Designation:
        </td>
        <td style="width: 325px">
          <asp:TextBox ID="DesignationTextBox" runat="server" Text='<%# 
            Bind("Designation") %>' Width="248px"></asp:TextBox>
        </td>
      </tr>
    </table>
    &nbsp;<br />
    <asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True"
      CommandName="Insert"  Text="Insert"></asp:LinkButton>
      <asp:LinkButton ID="InsertCancelButton" runat="server" 
        CausesValidation="False" CommandName="Cancel"
        Text="Cancel"></asp:LinkButton>
  </InsertItemTemplate>
</asp:FormView>

In order to show error and warning messages, I used the ObjectDataSource control's Updated and Deleted events. The ObjectDataSource control doesn't automatically update the e.AffectedRows property of the EventArgs-derived parameter passed to the Updated and Deleted event handlers; instead, this value is returned as an object so you need to convert it to an integer before assigning it to the AffectedRows property in the ObjectDataSource control's Updated and Deleted events. Later this value is used to determine concurrency related exceptions in the RowUpdated and RowDeleted events of the GridView control by checking the e.Exception property. The events of data-bound controls are listed below to check concurrency:

  • RowUpdated - This event is raised when the GridView control updates the row. A GridViewUpdatedEventArgs object is passed to the event-handling method.
  • RowDeleted- This event is raised when GridView control deletes the row. A GridViewDeletedEventArgs object is passed to the event-handling method.
  • ItemInserted - This event is raised when FormView control inserts the record. A FormViewInsertedEventArgs object is passed to the event-handling method.

All these passed argument objects in event handling methods allow you to determine the number of rows affected and any exceptions that might have occurred.

You can use the AffectedRows count and on that basis display a message on the page. These events are useful to perform exception handling. Now go ahead and drag another label control onto the web page to display the messages. Ultimately, your page should look something like Figure 5.

Figure 5. The sample application in design view

When you click on the link named View Employee Category wise List, a new page will open, entitled Employee Categorywise List. This page contains one DropDownList, a GridView and two ObjectDataSource controls. On the selection of an employee category, a GridView will display only employees belonging to the selected category. So I just need to add two more methods in the Employee class.

<DataObjectMethod(DataObjectMethodType.Select)> _
  Public Shared Function GetEmployeesByCategory(ByVal strEmpCategory As 
    String) As List(Of Employee)
    Dim sql As String = "SELECT EmpId, FirstName, MiddleName, LastName, 
      EmpCategory, Designation " _
      & "FROM Employee WHERE EmpCategory='" & strEmpCategory & "'"
    Dim cmd As OleDbCommand = _
      New OleDbCommand(sql, New OleDbConnection(GetConnectionString))
    cmd.Connection.Open()
    Dim dr As OleDbDataReader = _
      cmd.ExecuteReader(CommandBehavior.CloseConnection)
    Dim Employees As New List(Of Employee)
    Do While dr.Read
      Dim objEmployee As Employee = New Employee
      objEmployee.EmpId = CType(dr("EmpId"), Long)
      objEmployee.FirstName = dr("FirstName").ToString
      objEmployee.MiddleName = dr("MiddleName").ToString
      objEmployee.LastName = dr("LastName").ToString
      objEmployee.EmpCategory = dr("EmpCategory").ToString
      objEmployee.Designation = dr("Designation").ToString
      Employees.Add(objEmployee)
    Loop
    dr.Close()
    Return Employees
  End Function
<DataObjectMethod(DataObjectMethodType.Select)> _
  Public Shared Function GetEmpCategory() As List(Of Employee)
    Dim sql As String = "SELECT DISTINCT EmpCategory " _
      & "FROM Employee"
    Dim cmd As OleDbCommand = _
      New OleDbCommand(sql, New OleDbConnection(GetConnectionString))
    cmd.Connection.Open()
    Dim dr As OleDbDataReader = _
    cmd.ExecuteReader(CommandBehavior.CloseConnection)
    Dim Employees As New List(Of Employee)
    Do While dr.Read
      Dim objEmployee As Employee = New Employee
      objEmployee.EmpCategory = dr("EmpCategory").ToString
      Employees.Add(objEmployee)
    Loop
    dr.Close()
    Return Employees
  End Function

The GetEmpCategory() method returns the distinct employee category names. The name of this method is stored in the ObjectDataSource1 control's SelectMethod property. Now I bind the ObjectDataSource1 control with the DropDownList control. Next I'll take a look at the GetEmployeesByCategory() method, it has a parameter. I bind this method to ObjectDataSource2 control's SelectMethod property. When you click on the Next button in the wizard, a new wizard step named Define Parameters will appear. Figure 6 shows a screen shot for defining the parameter in the wizard.

Figure 6. Defining a parameter for an ObjectDataSource instance

For the ObjectDataSource2 control, the DropDownList control's SelectedValue is passed as a control parameter. Set DropDownList control's AutoPostBack attribute to True. So when you select a category in the DropDownList control, the proper employees will be listed in the GridView control (see Figure 7).

Figure 7. Employee category wise list

The GridView displays the employee records belonging to the Staff category only. In this way the ObjectDataSource control uses parameters in the SelectMethod.

Conclusion

In ASP.NET 2.0, it is possible to develop 3-tier web applications using the ObjectDataSource control. The ObjectDataSource makes it remarkably easy to data bind to middle-tier objects. The main advantage of using the ObjectDataSource control is reusability, scalability and ease of code maintenance. In this article I've used an example to help show how to create a 3- tier application that performs all database tasks that make up CRUD (Create, Retrieve, Update and Delete). The ObjectDataSource allows complete customization to incorporate business rules so it is very useful in developing scalable web applications.

Founders at Work


    1. Thank you for this very simple but very interesting and complete tutorial!!!
      I was looking for something like that!!!
      Wonderful
      bye



    1. It is good…
      This application is simple
      But it has all the function
      That needed…


    1. Gav says:

      Great article, but in order to truly encapsulate your Employee object shouldn’t the CRUD methods be part of the class? And if so how would you then use the objectdatasource… I assume you would use it in the same way but would need to ensure that an instance of employee was declared prior to calling the C, R, U or D.

      Also I couldn’t find the download location for the Source Files :$

      Cheers


    1. sivaguru says:

      fine.i understood basic idea of this tutorial.thanks




Add your comments

Please keep your comments relevant to this blog entry: inappropriate or purely promotional comments may be removed. To add hyperlink, please follow this example: "your link text":http://your.link.url