Docstoc

N-tier application Development

Document Sample
N-tier application Development Powered By Docstoc
					When .NET Framework was first introduced, it provided excellent features that made the construction of ASP.NET applications a
breezy experience. Now the next version of .NET Framework (version 2.0) along with SQL Server 2005 builds on the foundation
of the previous versions and introduces some new features that can greatly aid in the design and development of N-Tier
ASP.NET 2.0 applications. In this article, I will show you to how to construct an N-Tier ASP.NET 2.0 Web application by
leveraging the new features of ASP.NET 2.0 and SQL Server 2005 such as TableAdapter Configuration Wizard,
ObjectDataSource Control, App_Code directory to store reusable components, Master Pages, CLR Stored Procedures, and
Caching. Along the way, I will also highlight the best practices of using the new ASP.NET features for building N-Tier enterprise
class Web applications. From an implementation standpoint, Part-1 of this article will focus on the creation of CLR stored
procedures and the data access components in addition to describing the overall architecture of the sample application. Part-2 will
focus on the business logic layer object, ASP.NET user interface pages, caching and so on.

Introduction

Designing N-Tier client/server architecture is no less complex than developing two-tier architecture, however the N-Tier
architecture, produces a far more flexible and scalable client/server environment. In two-tier architecture, the client and the server
are the only layers. In this model, both the presentation layer and the middle layer are handled by the client. N-Tier architecture
has a presentation layer and three separate layers - a business logic layer and a data access logic layer and a database layer. The
next section discusses each of these layers in detail.

Different Layers of an N-Tier application

In a typical N-Tier environment, the client implements the presentation logic (thin client). The business logic and data access
logic are implemented on an application server(s) and the data resides on database server(s). N-tier architecture is typically thus
defined by the following layers:

        Presentation Layer: This is a front-end component, which is responsible for providing portable presentation logic. Since
         the client is freed of application layer tasks, which eliminates the need for powerful client technology. The presentation
         logic layer consists of standard ASP.NET web forms, ASP pages, documents, and Windows Forms, etc. This layer
         works with the results/output of the business logic layer and transforms the results into something usable and readable
         by the end user.
        Business Logic Layer: Allows users to share and control business logic by isolating it from the other layers of the
         application. The business layer functions between the presentation layer and data access logic layers, sending the client's
         data requests to the database layer through the data access layer.
        Data Access Logic Layer: Provides access to the database by executing a set of SQL statements or stored procedures.
         This is where you will write generic methods to interface with your data. For example, you will write a method for
         creating and opening a SqlConnection object, create a SqlCommand object for executing a stored procedure, etc. As the
         name suggests, the data access logic layer contains no business rules or data manipulation/transformation logic. It is
         merely a reusable interface to the database.
        Database Layer: Made up of a RDBMS database component such as SQL Server that provides the mechanism to store
         and retrieve data.

Now that you have a general understanding of the different layers in a N-Tier application, let us move onto discuss the
implementation of a N-Tier Web application.

Implementation

In this article, I will consider an example web site (that displays authors and author titles information) constructed using N-Tier
principles and use the example Web site to demonstrate the new features of ASP.NET 2.0 and SQL Server 2005. The sample
Web site shown in this example is very simple and straightforward and will consist of only two pages: the first page will show the
list of authors from the pubs database and the second page will display the list of titles specific to a selected author.

Please note that this article is not aimed at providing an exhaustive coverage of the individual features of ASP.NET 2.0, instead it
only focuses on helping the readers understand the features of ASP.NET 2.0 and SQL Server 2005 that are essential to building a
N-Tier web application.
Architecture of the Example Application

The following screenshot shows the different layers in the example application. It also highlights the important characteristics of
the example application.




Some of the important characteristics of the sample application are as follows:

        The stored procedures in the SQL Server 2005 database are created using C#. The ability to create stored procedures in
         managed code enables complex business logic to be executed close to the database resulting in performance
         improvements. The compiled nature of the stored procedure also results in increased performance.
        The data access layer classes are generated using the new TableAdapter Configuration Wizard, which enables you to
         create data access layer classes without writing a single line of code.
        ASP.NET Web forms in the user interface layer are generated using master pages, providing a consistent look and feel
         for the entire application.
        Web forms utilize ObjectDataSource control to directly bind the output of the middle tier methods to data bound
         controls such as a GridView control.
        Web forms also take advantage of caching of database contents to increase the performance and throughput of the web
         application. This is made possible by the use of the database cache invalidation mechanism that can automatically
         remove specific items from the cache when the data in the database table changes.

Implementation of the Application

I will discuss the implementation by discussing each of the above layers, starting with the database layer.

Database Objects using Managed Code

One of the neat features of SQL Server 2005 is the integration with the .NET CLR. The integration of CLR with SQL Server
extends the capability of SQL Server in several important ways. This integration enables developers to create database objects
such as stored procedures, user defined functions, and triggers by using modern object-oriented languages such as VB.NET and
C#. In this article, I will demonstrate how to create the stored procedures using C#. Before looking at the code, let us understand
the pros and cons of using managed language in the database tier to create server side objects.

T-SQL Vs Managed Code

Although T-SQL, the existing data access and manipulation language, is well suited for set-oriented data access operations, it also
has limitations. It was designed more than a decade ago and it is a procedural language rather than an object-oriented language.
The integration of the .NET CLR with SQL Server enables the development of stored procedures, user-defined functions,
triggers, aggregates, and user-defined types using any of the .NET languages. This is enabled by the fact that the SQL Server
engine hosts the CLR in-process. All managed code that executes in the server runs within the confines of the CLR. The managed
code accesses the database using ADO.NET in conjunction with the new SQL Server Data Provider. Both Visual Basic .NET and
C# are modern programming languages offering full support for arrays, structured exception handling, and collections.
Developers can leverage CLR integration to write code that has more complex logic and is more suited for computation tasks
using languages such as Visual Basic .NET and C#. Managed code is better suited than Transact-SQL for number crunching and
complicated execution logic, and features extensive support for many complex tasks, including string handling and regular
expressions. T-SQL is a better candidate in situations where the code will mostly perform data access with little or no procedural
logic. Even though the example you are going to see in this article is best written using T-SQL, I will take the managed code
approach and show you how to leverage that feature.

Creating CLR Based Stored Procedures

For the purposes of this example, create a new SQL Server Project using Visual C# as the language of choice in Visual Studio
2005. Since you are creating a database project, you need to associate a data source with the project. At the time of creating the
project, Visual Studio will automatically prompt you to either select an existing database reference or add a new database
reference. Choose pubs as the database. Once the project is created, select Add Stored Procedure from the Project
menu. In the Add New Item dialog box, enter Authors.cs and click Add button. After the class is created, modify the code
in the class to look like the following.

using    System;
using    System.Data;
using    System.Data.Sql;
using    System.Data.SqlClient;
using    System.Data.SqlTypes;
using    Microsoft.SqlServer.Server;

public class Authors
{
[SqlProcedure]
public static void GetAuthors()
{
SqlPipe sp = SqlContext.Pipe;
using (SqlConnection conn = new
SqlConnection("context connection=true"))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.CommandText = "Select DatePart(second, GetDate()) " +
" As timestamp,* from authors";
SqlDataReader rdr = cmd.ExecuteReader();
sp.Send(rdr);
}
}

[SqlProcedure]
public static void GetTitlesByAuthor(string authorID)
{
string sql = "select T.title, T.price, T.type, " +
"T.pubdate from authors A" +
" inner join titleauthor TA on A.au_id = TA.au_id " +
" inner join titles T on TA.title_id = T.title_id " +
" where A.au_id = '" + @authorID + "'";
using (SqlConnection conn = new
SqlConnection("context connection=true"))
{
conn.Open();
SqlPipe sp = SqlContext.Pipe;
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.CommandText = sql;
SqlParameter paramauthorID = new
SqlParameter("@authorID", SqlDbType.VarChar, 11);
paramauthorID.Direction = ParameterDirection.Input;
paramauthorID.Value = authorID;
cmd.Parameters.Add(paramauthorID);
SqlDataReader rdr = cmd.ExecuteReader();
sp.Send(rdr);
}
}
}

Let us examine the above lines of code. The above code starts by importing the required namespaces and then declares a class
named Authors. There are two important classes in the Microsoft.SqlServer.Server namespace that are specific to the in-proc
provider:

        SqlContext: This class encapsulates the extensions required to execute in-process code in SQL Server 2005. In addition
         it provides the transaction and database connection which are part of the environment in which the routine executes.
        SqlPipe: This class enables routines to send tabular results and messages to the client. This class is conceptually similar
         to the Response class found in ASP.NET in that it can be used to send messages to the callers.

The Authors class contains two static methods named GetAuthors and GetTitlesByAuthor. As the name suggests, the GetAuthors
method simply returns all the authors from the authors table in the pubs database and the GetTitlesByAuthor method returns all
the titles for a specific author.

Inside the GetAuthors method, you start by getting reference to the SqlPipe object by invoking the Pipe property of the
SqlContext class.

SqlPipe sp = SqlContext.Pipe;

Then you open the connection to the database using the SqlConnection object. Note that the connection string passed to the
constructor of the SqlConnection object is set to "context connection=true" meaning that you want to use the context of the
logged on user to open the connection to the database.

using (SqlConnection conn = new SqlConnection("context connection=true"))

Here open the connection to the database using the Open() method.

conn.Open();

Then you create an instance of the SqlCommand object and set its properties appropriately.

SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.CommandText = "Select DatePart(second, GetDate()) " + " As timestamp,* from
authors";

Finally you execute the sql query by calling the ExecuteReader method of the SqlCommand object.

SqlDataReader rdr = cmd.ExecuteReader();

Then using the SqlPipe object, you then return tabular results and messages to the client. This is accomplished using the Send
method of the SqlPipe class.

sp.Send(rdr);

The Send method provides various overloads that are useful in transmitting data through the pipe to the calling application.
Various overloads of the Send method are:

        Send (ISqlDataReader) - Sends the tabular results in the form of a SqlDataReader object.
        Send (ISqlDataRecord) - Sends the results in the form of a SqlDataRecord object.
        Send (ISqlError) - Sends error information in the form of a SqlError object.
        Send (String) - Sends messages in the form of a string value to the calling application.

Both the methods in the Authors class utilize one of the Send methods that allows you to send tabular results to the client
application in the form of a SqlDataReader object. Since the GetTitlesByAuthor method implementation is very similar to the
GetAuthors method, I will not be discussing that method in detail.

Now that the stored procedures are created, deploying it is very simple and straightforward. Before deploying it, you need to
build the project first. To build the project, select Build->Build <ProjectName> from the menu. This will compile all the
classes in the project and if there are any compilation errors, they will be displayed in the Error List pane. Once the project is
built, you can then deploy it onto the SQL Server by selecting Build->Deploy <ProjectName> from the menu. This will
not only register the assembly in the SQL Server but also deploy the stored procedures in the SQL Server. Once the stored
procedures are deployed to the SQL Server, they can then be invoked from the data access layer, which is the topic of focus in the
next section.

Before executing the stored procedure, ensure you execute the following sql script using SQL Server Management Studio to
enable managed code execution in the SQL Server.

EXEC sp_configure 'clr enabled', 1;
RECONFIGURE WITH OVERRIDE;
GO

Data Access Layer using TableAdapter Configuration Wizard

Traditionally the process you employ to create data access layer classes is a manual process, meaning that you first create a class
and then add the appropriate methods to it. With the introduction of Visual Studio 2005, Microsoft has introduced a new
TableAdapter Configuration Wizard that makes creating a data access logic layer class a breezy experience. Using this wizard,
you can create a data access logic layer component without having to write a single line of code. This increases the productivity
of the developers to a great extent. Once you create those classes, you can consume them exactly the same way you consume
built-in objects. Before looking at an example, let us briefly review what a TableAdapter is. A TableAdapter connects to a
database, executes queries, or stored procedures against a database, and fills a DataTable with the data returned by the query or
stored procedure. In addition to filling existing data tables with data, TableAdapters can return new data tables filled with data.
The TableAdapter Configuration Wizard allows you to create and edit TableAdapters in strongly typed datasets. The wizard
creates TableAdapters based on SQL statements or existing stored procedures in the database. Through the wizard, you can also
create new stored procedures in the database.

This section will discuss the creation of a data access component that will leverage the stored procedures created in the previous
step. To start, create a new ASP.NET web site named NTierExample in Visual C# by selecting New Web Site from the
File menu as shown below.
To create a data component, begin by right clicking on the web site and selecting Add New Item from the context menu. In the
Add New Item dialog box, select DataSet from the list of templates. Change the name of the file to Authors.xsd and
click Add.




When you click Add, you will be prompted if you want to place the component inside the App_Code directory. Click OK in the
prompt and this will bring up the TableAdapter Configuration Wizard. In the first step of the TableAdapter Configuration
Wizard, you need to specify the connection string and in the second step you will be prompted if you want to save the connection
string in the web.config file. In this step, save the connection string to the web.config file by checking the check box.
In the next step, you will be asked to choose a command type. Select the Use existing stored procedures option as
shown below and click Next.




Clicking Next in the above screen brings up the following screen wherein you select the stored procedure to use.
Click Next in the above dialog box and you will see the Choose Methods to Generate dialog box wherein you can
specify the name of the method that will be used to invoke the stored procedure selected in the previous step. Specify the name of
the method as GetAuthors as shown below:
Clicking Next in the above screenshot results in the following screen wherein you just hit Finish.
When you click on Finish, Visual Studio will create the required classes for you. After the classes are created, you need to
rename the class to Authors. After making all the changes, the final output should look as follows.
That's all there is to creating a data access component using the TableAdapter Configuration Wizard. As you can see, all you have
to do is to provide the wizard with certain information and Visual Studio hides all the complexities of creating the underlying
code for you.

Now that you have created the data access layer method for the GetAuthors stored procedure, you need to do the same thing for
the GetTitlesByAuthor stored procedure. To this end, add another TableAdapter to the Authors.xsd by selecting Data->Add-
>TableAdapter from the menu and follow through the wizard steps. Remember to specify the stored procedure name as
GetTitlesByAuthor this time. Note that at the time of writing this article using Visual Studio 2005 Beta 2, I encountered some
problems in getting the wizard to work because of some bugs. If you run into any problem with the wizard, simply exit from the
wizard, select the appropriate TableAdapter from the designer and select View->Properties Window from the menu.
Through the properties dialog box, you should be able to perform all the configurations related to a TableAdapter.

Storing Utility Classes in App_Code Directory

You might remember that when you created the data component, you placed the data component class inside the App_Code
directory, which is a special directory used by ASP.NET. It is very similar to bin directory, but with the following exceptions:
While the bin directory is designed for storing pre-compiled assemblies used by your application, the App_Code directory is
designed for storing class files to be compiled dynamically at run time. This allows you to store classes for business logic
components, data access components, and so on in a single location in your application, and use them from any page. Because the
classes are compiled dynamically at run time and automatically referenced by the application containing the App_Code directory,
you don't need to build the project before deploying it, nor do you need to explicitly add a reference to the class. ASP.NET
monitors the App_Code directory and when new components are added, it dynamically compiles them. This enables you to easily
make changes to a component and deploy with a simple XCOPY or with a drag-and-drop operation. In addition to simplifying the
deployment and referencing of components, the \App_Code directory also greatly simplifies the creation and accessing of
resource files (.resx) used in localization, as well as automatically generating and compiling proxy classes for WSDL files
(.wsdl).

With the introduction of this new directory, you might be wondering when to use this directory when compared to the bin
directory. If you have an assembly that you want to use in your web site, create a bin subdirectory and then copy the .dll to that
subdirectory. If you are creating reusable components that you want to use only from your ASP.NET pages, place them under the
App_Code directory. Note that any class you add to the App_Code directory is visible only within that Web site meaning that it
will not be visible outside of that Web site. So if you are creating a class that needs to be shared across multiple Web sites, you
will be better off creating that class as part of a class library project and share that project among those Web sites.

Conclusion

In this installment, you have understood the new features of SQL Server 2005 utilized to create stored procedures using managed
language such as C#. After that, you have also seen the steps involved in creating the data access components using TableAdapter
Configuration Wizard that greatly simplified the process of creating a data access component. In Part-2 of this article, we will see
how to consume this data access components from a business logic layer. We will also look at the use of master pages in creating
the user interface, and caching features in ASP.NET 2.0 and so on.




PART 2

we looked at the application architecture of a N-tier Web application using ASP.NET 2.0 and SQL Server 2005. We have also
understood the creation of CLR managed procedures and data access components. In this installment, we will look at the rest of
the components of the application such as business logic layer, user interface logic and so on. While looking at these features, we
will also understand the new features of ASP.NET 2.0 such as ObjectDataSource control, master pages, and Caching support that
greatly aid in simplifying the development of a N-tier Web application.

Creation of Business Logic Layer

In this example, since there is not much of business logic, the business layer methods will simply act as stubs that will invoke the
data access layer methods. Create a new class named AuthorsBiz and place that under the App_Code directory as well. Modify
the code in the class to look as shown below.

using System;
using System.Data;
public class AuthorsBiz
{
   public AuthorsBiz()
   {
   }
   public DataTable GetAuthors()
   {
      AuthorsTableAdapters.AuthorsTableAdapter authorDB = new
        AuthorsTableAdapters.AuthorsTableAdapter();
      return authorDB.GetAuthors();
   }
   public DataTable GetAuthorTitles(string authorID)
   {
      AuthorsTableAdapters.AuthorTitlesTableAdapter authorDB = new
        AuthorsTableAdapters.AuthorTitlesTableAdapter();
      return authorDB.GetTitlesByAuthor(authorID);
   }
}

As you can see from the above, the methods in the AuthorsBiz class simply invoke the data component methods and route the
results back to the caller. Now that you have created the business logic and data access layers, let us move onto the user interface
layer, which will provide the desired functionality by taking advantage of the classes you have created so far.
Creation of User Interface Layer

As mentioned before, the user interface layer will consist of two pages named Authors.aspx and AuthorTitles.aspx that will
display the authors and the titles for a specific author respectively. To ensure all the pages in the web site have a consistent look
and feel, ASP.NET 2.0 introduces a new feature named master pages. In this approach, a common base master file that contains
the common layout for all the pages is created and all the pages in the web site (called content pages) are inherited from the
master page. At runtime when the content page is requested through the browser, ASP.NET merges the output of the content page
with the master page thereby providing a seamless way to reuse the master page layout and logic. The next section will
demonstrate the steps involved in creating a master page and utilizing it from content pages.

Creating Consistent User Interface using Master Pages

With ASP.NET 2.0 master pages, you isolate the look and feel and standard behavior for all the pages in your application and
move them to a master page. In the master page, you add placeholders (known as ContentPlaceHolder control) for the content
pages (or child pages) to add their custom content. When users request the content pages, the output of the content pages are
merged with the output of the master page, resulting in an output that combines the layout of the master page with the output of
the content page.

As mentioned before, the master page defines content areas using the ContentPlaceHolder control, and the content pages place
their content in the areas identified by the ContentPlaceHolder control in the master page. Pages that use a master page to define
the layout can place content only in the areas defined by the ContentPlaceHolder, thus enabling a consistent site design. Master
pages are saved with the file extension .master. Apart from containing all the contents that are required for defining the standard
look and feel of the application, the master pages also contain all the top-level HTML elements for a page, such as <html>,
<head>, and <form>. For this article, add a master page named CommonMaster.Master to the page web site using the Add
New Item dialog box. Modify the code in the master page to look as shown below:

<%@ master language="C#" %>
<html>
<head id="Head1" runat="server">
  <title>Master Page</title>
</head>
<body>
<form id="Form1" runat="server">
  <table id="header" style="WIDTH: 100%; HEIGHT: 80px"
    cellspacing="1" cellpadding="1" border="1">
    <tr>
       <td style="TEXT-ALIGN: center; width: 100%; height: 74px;"
         bgcolor=teal>
         <asp:label runat="server" id="Header" Font-Size="12pt"
           Font-Bold="True">Authors Information</asp:label>
       </td>
    </tr>
  </table>
  <b/>
  <table id="leftNav" style="WIDTH: 108px; HEIGHT: 100%"
    cellspacing="1" cellpadding="1" border="1">
    <tr>
       <td style="WIDTH: 100px">
         <table>
           <tr>
             <td>
                <a href="Home.aspx">Home</a>
             </td>
           </tr>
           <tr>
             <td>
                <a href="Authors.aspx">Authors List</a>
             </td>
           </tr>
         </table>
      </td>
    </tr>
  </table>
  <table id="mainBody" style="LEFT: 120px; VERTICAL-ALIGN: top;
    WIDTH: 848px; POSITION: absolute; TOP: 94px; HEIGHT: 100%"
    border="1">
    <tr>
      <td width="100%" style="VERTICAL-ALIGN: top">
         <asp:contentplaceholder id="middleContent"
           runat="Server"></asp:contentplaceholder>
      </td>
    </tr>
  </table>
</form>
</body>
</html>

The above code looks similar to a traditional ASP.NET page and contains simple HTML and ASP.NET controls. The main
difference between this page and a standard ASP.NET page is the use of the Master directive and the file suffix .master. Also
note the use of the ContentPlaceHolder control, which dictates where content pages can insert content. The id attribute uniquely
identifies the placeholder, allowing more than one placeholder to be in a master page. The master page can have code as well as
content, allowing the master page to render contents dynamically. The above code defines a header and a left navigation bar as
well as the body of the page using HTML table elements. Inside the body table, there is an asp:contentplaceholder control, which
will be linked in all the content pages so that the content pages can insert their own content. Any content page that uses the above
master page will automatically inherit the header, left navigation and the body from the master page.

Now that you have created the master page, let us create a content page that can leverage the master page. To this end, create a
Web Form using Visual Studio 2005, name it as Authors.aspx as shown below.




Note that in the above screenshot, Select master page option is selected and this will result in the master page picker
dialog box being displayed. Select CommonMaster.master file from the list. This is shown below.
Click OK in the above dialog box. After the page is created, modify the code of the Authors.aspx Web page to look as follows:

<%@ Page Language="C#" MasterPageFile="~/CommonMaster.master" %>
<asp:content id="Content1" contentplaceholderid="middleContent"
  runat="server">
  <asp:objectdatasource runat="server" id="authorsSource"
    typename="AuthorsBiz" selectmethod="GetAuthors">
  </asp:objectdatasource>
  <asp:gridview runat="server" AutoGenerateColumns="false"
    id="authorsView" datasourceid="authorsSource">
    <alternatingrowstyle backcolor="Silver"></alternatingrowstyle>
    <Columns>
      <asp:HyperLinkField DataTextField="au_id"
        HeaderText="Author ID" DataNavigateUrlFields="au_id"
        DataNavigateUrlFormatString="AuthorTitles.aspx?AuthorID={0}">
      </asp:HyperLinkField>
      <asp:BoundField HeaderText="Last Name"
        DataField="au_lname"></asp:BoundField>
      <asp:BoundField HeaderText="First Name"
        DataField="au_fname"></asp:BoundField>
      <asp:BoundField HeaderText="Phone"
        DataField="phone"></asp:BoundField>
      <asp:BoundField HeaderText="Address"
        DataField="address"></asp:BoundField>
      <asp:BoundField HeaderText="City"
        DataField="city"></asp:BoundField>
      <asp:BoundField HeaderText="State"
        DataField="state"></asp:BoundField>
      <asp:BoundField HeaderText="Zip"
        DataField="zip"></asp:BoundField>
      <asp:BoundField HeaderText="Timestamp"
        DataField="timestamp"></asp:BoundField>
    </Columns>
  </asp:gridview>
</asp:content>

As part of the page directive, there is a new attribute named MasterPageFile that allows you to specify the master page you want
to use. Then you define an asp:content control and link that up to the master page's asp:contentplaceholder using the
contentplaceholderid attribute. Inside the asp:content element, two controls are defined: an ObjectDataSource and a GridView
control. The ObjectDataSource control acts as a data source for the GridView control, which simply displays all the authors in a
list. An ObjectDataSource control is a new control that is introduced with ASP.NET 2.0 that greatly simplifies the way in which
the middle tier business objects are consumed from an ASP.NET page. Let us discuss this control in detail.

ObjectDataSource Control and N-Tier Development

ASP.NET 2.0 provides excellent native support for N-Tier application design by introducing the ObjectDataSource control,
which is one of the most compelling new entries in the ASP.NET 2.0 arsenal of controls and components. It promotes the use of a
strong object model in the middle tier of distributed applications and makes it easier than ever to set up a direct link between the
business logic classes and the user interface layer.

In ASP.NET v1.x, the middle tier would expose some sort of custom business objects to the user interface and then a developer
would bind the data to the controls programmatically. Now with ASP.NET 2.0, this binding code is no longer necessary thanks to
the ObjectDataSource control. With this control, you can simply bind to an output of an object's method directly to data-bound
controls such as GridView, dropdown list and so on.

In the previous example, the ObjectDataSource control is used to directly bind the results of the GetAuthors method in the
AuthorsBiz class and display them in a GridView control. This is shown below:

   <asp:objectdatasource runat="server" id="authorsSource"
     typename="AuthorsBiz" selectmethod="GetAuthors">
   </asp:objectdatasource>

The ObjectDataSource control is used to instantiate the AuthorsBiz object that will then be responsible for retrieving the
appropriate data from the database through the data access layer. The first property you need to set for this control is the
TypeName property that tells the control the name of the class to instantiate. This can be the name of any class included in or
referenced by the user interface assembly as long as it has a default public constructor (no parameters). Next, you specify the
methods of the object, which will handle Select, Update, Insert, or Delete requests. To specify a method used to retrieve data, set
the SelectMethod property. The select method must return an object that can be bound to a control such as a Dataset,
XmlDocument, or Collection. If the method being invoked requires parameters, you can specify the parameters using the
SelectParameters collection which is defined using the <SelectParameters> sub element. You can see an example of this in the
implementation of the AuthorTitles.aspx page.

Now that you have had a look at the Authors.aspx page, let us move onto discuss the AuthorTitles.aspx page. Code for the
AuthorTitles.aspx page is as follows:

<%@ Page Language="C#" MasterPageFile="~/CommonMaster.master" %>
<asp:content id="Content1" contentplaceholderid="middleContent"
  runat="server">
  <asp:objectdatasource runat="server" id="authorTitlesSource"
    typename="AuthorsBiz" selectmethod="GetTitlesByAuthor">
    <SelectParameters>
      <asp:QueryStringParameter Type="String" Direction="Input"
        Name="authorID" QueryStringField="AuthorID" />
    </SelectParameters>
  </asp:objectdatasource>
  <asp:gridview runat="server" id="authorTitlesView"
    datasourceid="authorTitlesSource">
    <alternatingrowstyle backcolor="Silver"></alternatingrowstyle>
  </asp:gridview>
</asp:content>

As you can see, the above code is very similar to the Authors.aspx except for the difference that the ObjectDataSource control
uses asp:QueryStringParameter element to pass the author id (which is retrieved from the page query string) as an argument to
the GetAuthorTitles method of the AuthorsBiz object.
Caching

Caching is a technique that allows you to keep frequently accessed pages or resources (that are expensive to construct) in the
memory instead of recreating them from scratch every time. If you have data on the web page that does not change frequently and
it is expensive construct then they can be considered as good candidates for caching. Caching is one of the powerful features that
can be immensely useful in increasing the performance of a web application. ASP.NET 1.x Cache API was a revolutionary
feature that provided capabilities such as declarative output caching, programmatic output caching, and invalidation of cached
items when the contents of an XML file or another cached item changes and so on. Even though all these features were of
excellent use in increasing the performance of the web application, ASP.NET 1.x did not provide a mechanism for invalidating
the data in the cache object when the data in a database changes. This is a much sought after feature that will finally ship with the
ASP.NET 2.0 version. Since the authors list does not change frequently, I will show you how to cache the authors list in the
object data source control. As part of this, I will also demonstrate how to take advantage of the cache invalidation mechanism
features so that the cached authors list can be automatically removed when the authors table changes in the database.

As mentioned before, one of the most interesting features of ASP.NET 2.0 is the introduction of database-triggered cache
invalidation. This is a very common capability most of the applications will require. ASP.NET 2.0 addresses this by providing the
database triggered cache invalidation capability that will allow you to ensure that the items in the cache are kept up-to-date with
the changes in the database.

SQL Server Based Cache Invalidation Mechanism

The SQL Server based cache invalidation mechanism works with SQL Server 7.0 and above. However with SQL Server 7.0 and
2000, only table level cache invalidation mechanism is supported. This means that the cached items will be automatically
invalidated any time the data in the table changes. The next release of SQL Server (code-named Yukon) called SQL Server 2005
will also feature row-level cache invalidation mechanism providing a finer level of accuracy over the cached data.

In Sql Server 7 and Sql Server 2000, table level cache invalidation is supported using a polling system. Through this system, the
ASP.NET process will poll the database (pull model) every so many seconds to check and see which tables have changed since it
last checked. Even though the pull model works for most cases, it is not an efficient approach. However this will be enhanced in
SQL Server 2005 to have SQL Server 2005 actually notify (Push model) ASP.NET, whenever a particular row of data has been
modified. SQL Server 2005 accomplishes this by using a feature named Notification Delivery Services (that uses ports 80),
which directly interacts with HTTP.SYS of IIS 6.0 to notify the web server of updates to the specific rows.

Before you can establish cache dependency with SQL Server, you need to perform the following steps.

        You must have <cache> element in the configuration file (web.config)
        You also need to perform one time setup of the tables or databases you want to monitor using either the aspnet_regsql
         utility or the EnableTableForNotifications method.

After you have completed the above steps, ASP.NET can start invalidating the data in the cache when the SQL Server data
changes. To begin, add the appropriate cache related settings in the web.config file as shown below.

<configuration>
  <connectionStrings>
    <add name="pubsConnectionString"
connectionString="Server=localhost;Database=Pubs;integrated
  security=true" />
  </connectionStrings>
  <system.web>
    <caching>
       <sqlCacheDependency enabled="true">
   <databases>
     <add name="Pubs"
        connectionStringName="pubsConnectionString"
        pollTime="60000" />
   </databases>
</sqlCacheDependency>
    </caching>
  </system.web>
</configuration>

In the above configuration entries, you specify the name of the database in which you want to enable the cache notification
mechanism using the <caching> element. As you can see, there is a new section in web.config called <connectionString> in
which you add the connection strings to the database. Once you add the connectionString to the connectionStrings section, you
can then reference it from the sqlCacheDependency/databases section.

Next step is to enable the specific tables in the pubs database for notification. Note that this step is not required for SQL Server
2005. This example will make use of the aspnet_regsql utility to accomplish this. The aspnet_regsql utility creates an extra table
named AspNet_SqlCacheTablesForChangeNotification that is used to keep track of the changes to all the monitored tables in the
database. It also creates a number of triggers and stored procedures to enable this capability. To run the aspnet_regsql utility,
open up the .NET Framework 2.0 SDK Command Prompt and enter the following command.

aspnet_regsql -S localhost -E -d pubs -ed

This will enable the database to support cache invalidation mechanism. Once you have enabled this for the pubs database, you
can now enable it for the individual tables contained in the pubs database. To enable cache invalidation for the authors table,
execute the following command.

aspnet_regsql -S localhost -E -d pubs -t authors -et

Now that you have created the plumbing required for the database cache invalidation, let us look at the steps involved in utilizing
it from the Authors.aspx page.

Enabling Caching in the ObjectDataSource Control

In this section, you will see how to enable caching at the ObjectDataSource control. There are three important properties that
need to be set in the ObjectDataSource control to enable caching. They are:

        EnableCaching - By setting this attribute to true, you enable caching in an ObjectDataSource control.
        CacheDuration - This property allows you to set or get the duration of the cached data in the ObjectDataSource control.
         This attribute is specified in terms of seconds.
        SqlCacheDependency - Specifies the connection string element value to use from the web.config file.

After adding the caching related attributes, the Authors.aspx looks as follows:

<%@ Page Language="C#" MasterPageFile="~/CommonMaster.master" %>
<asp:content id="Content1" contentplaceholderid="middleContent"
  runat="server">
  <asp:objectdatasource EnableCaching="true"
    SqlCacheDependency="Pubs:authors"
    CacheDuration="10000" runat="server" id="authorsSource"
    typename="AuthorsBiz" selectmethod="GetAuthors">
  </asp:objectdatasource>
  <asp:gridview runat="server" AutoGenerateColumns="false"
    id="authorsView" datasourceid="authorsSource">
    <alternatingrowstyle backcolor="Silver">
    </alternatingrowstyle>
    <Columns>
      <asp:HyperLinkField DataTextField="au_id"
        DataNavigateUrlFields="au_id"
        DataNavigateUrlFormatString="AuthorTitles.aspx?AuthorID={0}">
      </asp:HyperLinkField>
      <asp:BoundField DataField="au_lname"></asp:BoundField>
      <asp:BoundField DataField="au_fname"></asp:BoundField>
      <asp:BoundField DataField="phone"></asp:BoundField>
      <asp:BoundField DataField="address"></asp:BoundField>
      <asp:BoundField DataField="city"></asp:BoundField>
      <asp:BoundField DataField="state"></asp:BoundField>
      <asp:BoundField DataField="zip"></asp:BoundField>
    </Columns>
  </asp:gridview>
</asp:content>

The preceding code listing demonstrates sql cache invalidation with the ObjectDataSource control. As you can see, the
ObjectDataSource control contains both EnableCaching and SqlCacheDependency attributes. The SqlCacheDependency property
uses the following syntax.

SqlCacheDependency="Pubs:authors"

The attribute declaration lists the name of the connection string identifier, followed by the name of the database table. Because of
this attribute, any time data in the authors table of the Pubs database changes, the cached data will be automatically invalidated.
The connection string identifier name that you are specifying here should already be defined in the
caching\sqlCacheDependancy\databases section of the web.config file.

Putting It All Together

Now that you have understood the implementation of the application, let us test its functionality by navigating to the
Authors.aspx page using the browser. You should see an output that is somewhat similar to the following.




If you refresh the page again, you will see the same timestamp in the displayed output, which is due to the fact that you have
enabled caching on the ObjectDataSource control. Now to test the SQL Server based trigger invalidation, change the data in the
authors table in the pubs database and refresh the page. You should now see a change in the timestamp displayed in the page.
This clearly shows that the SQL Server based trigger invalidation mechanism automatically invalidates the output of the
ObjectDataSource control as soon as the data in the authors table changes. Clicking on the author id results in the following page
that displays all the titles for a specific author.
Conclusion

In this series of articles, you have understood a wide range of ASP.NET and SQL Server 2005 features utilized to create an N-
Tier ASP.NET 2.0 web based application. The sample application discussed in this article showcased the new features of .NET
Framework 2.0 such as TableAdapter Configuration Wizard, and App_Code directory. This article also discussed how the
ObjectDataSource control supports layered application design by allowing you to directly bind the output of an object's method
directly to the controls in an ASP.NET page. The architecture used by the example application provides a number of advantages.
They are as follows:

       Changes to the user interface or to the application logic are largely independent from one another, allowing the
        application to evolve easily to meet new requirements.
       Creating stored procedures using managed code provide performance improvements because of the compiled logic that
        gets executed close to the database server.
       If changes to the middle layer classes are required, they can be modified and deployed immediately onto the App_Code
        directory and the ASP.NET will pick up those changes immediately and compile them on-demand. This enables easy
        deployment of upgrades to the existing classes that contain the business logic.
       Using master pages in the presentation layer provide a huge advantage in terms of providing a consistent look and feel
        across all the pages in the web site.
       Caching of database tables results in increased performance. Also the new database cache invalidation provides the
        ability to keep the changes in the database up-to-date with the data in ASP.NET cache.
       The ability to generate data access logic classes (using Data Component Wizard) without writing a single line of code is
        a very powerful feature can go a long way in increasing the developers' productivity.
       ASP.NET 2.0 facilitates N-Tier application design by providing the ObjectDataSource control that is specifically suited
        for consuming middle tier objects. This new control enables "code-less" data binding by providing the ability to
        seamlessly integrate the data returned from the middle layer objects with the ASP.NET presentation layer.