One of the advanced features of ADO.NET 2.0 you can utilize from an ASP.NET page is creating and working with strongly typed DataSets.
Using the DataSet
class provided by the System.Data
namespace, in a typical DataSet
, you might access the name of a category like this:
DataRow row = categoriesDataSet.Tables["Categories"].Rows[0]; Response.Write(row["Name"]);
With strongly typed DataSets
, you will be able to access your data in a much more programmer-friendly fashion:
Response.Write(categoriesDataSet.Categories[0].Name);
As you can see, the second method is much easier to understand and write. The functionality just described is made possible by a convention in the .NET Framework known as strongly typed DataSets
. Strongly typed DataSets
are classes that inherit from a DataSet,
giving them a strongly typed nature based on an XSD structure you specify.
A typed DataSet
is not a built-in member of the .NET Framework. As you will discover, it is a generated class that inherits directly from the DataSet
class, and allows properties and methods to be customized from an XML schema that you specify. This class also contains other classes for DataTable
and DataRow
objects that are enhanced in similar ways. As a result, you can create schemas and classes for data that are customized precisely for your data, enabling you to write data access code more efficiently. Do note, however, that even though your code will be up and running more quickly, you will also be burdened eventually with keeping the structures of your strongly typed DataSets
up to date as your system changes.
As you may have guessed by now, strongly typed DataSets
require you to write XSD schemas. In fact, not every XSD schema qualifies to be a DataSet
, so it may be argued that you need to know specifically what is allowed in an XML schema that controls what aspect of a DataSet
. The good news, however, is that for a majority of your needs, Visual Studio makes it extremely easy to author strongly typed DataSets
. So as you add a new DataTable
, it creates and maintains an XSD schema underneath for you. In the case of strongly typed DataSets
, an XML schema provides a rich definition of the data types, relationships, keys, and constraints within the data it describes. The next section provides you with a discussion on how to create strongly typed DataSets
.
There are several ways to create strongly typed DataSets
. This article will illustrate the creation of strongly typed DataSets
in Visual Studio 2005.
Creating a Strongly Typed DataSet in Visual Studio 2005
Strongly typed DataSets
are merely generic DataSets
that have their columns and tables defined in advance, so the compiler already knows what they will contain. Each version of Visual Studio has made the process of strongly typing a DataSet
easier, and Visual Studio 2005 has lived up to this expectation by providing an easy-to-use interface for creating and managing strongly typed DataSets
. In this example, you will use the Production.Product table in the AdventureWorks database to demonstrate this feature. Simply perform the following steps:
- Open Visual Studio, and create a new ASP.NET web site.
- In Solution Explorer, right-click to add a new item, and select
DataSet
. Give it the nameProductDataSet.xsd
. Visual Studio will recommend placing theDataSet
file inside theApp_Code
folder, which you should allow it to do for you. - The
ProductDataSet.xsd
will open in design mode, and the TableAdapter Configuration Wizard will be launched. For now, just click Cancel, because you will add tables by dragging them from the Server Explorer. - Locate the Server Explorer Toolbox, navigate to your SQL Server 2005 database, and the AdventureWorks database.
- Drag the Production.Product table to your
DataSet
Designer window. The window should now resemble Figure 1.
Figure 1
As you can see from Figure 1, for each table that is added to the designer, Visual Studio creates a strongly typed DataTable
(the name is based on the original table) and a TableAdapter
. The DataTable
has all of its columns already defined. The table adapter is the object you will use to fill the table. By default, you have a Fill()
method that will find every row from that table.
This strongly typed DataSet
, as is, will return all of the records in the Product table. Since the Product table contains a lot of information, let us modify the default query to return only the products that belong to the supplied product category. To do this, right-click the ProductTableAdapter and select Add Query. Pick Use SQL statements and click the Next button. Then, choose SELECT, which returns rows, and click Next. Finally, enter the following query in the window (or use the Query Builder to accomplish the same task):
SELECT ProductID, Name, ProductNumber, MakeFlag FROM Production.Product Where ProductSubcategoryID = @ProductSubcategoryID
This SQL query is a simple SELECT
query with an @ProductSubcategoryID
parameter to narrow down the results. This will enable you to return the products that belong to the supplied category. Leaving the Fill a DataTable and Return a DataTable check boxes checked, click Finish. After adding this SELECT
statement, your designer should now have an extra query added to the ProductTableAdapter
, as shown in Figure 2.
Figure 2
Note that you can also build strongly typed DataSets
using a command-line utility called xsd.exe
. To create the strongly typed DataSet
based on the Categories.xsd
schema, use the following command:
xsd /d /l:CS Categories.xsd
Now that you have created the strongly typed DataSet
, the next step is to utilize it from an ASP.NET page.
Using the Strongly Typed DataSet in an ASP.NET Page
With the strongly typed DataSet
created, you can easily display this data in an ASP.NET page with just a few lines of code. Listing 1 discusses the ASP.NET page that utilizes the DataSet
created in the previous section.
Listing 1: Using a Strongly Typed DataSet
<%@ Page Language="C#" %> <%@ Import Namespace="System.Data" %> <script runat="server"> void Page_Load(object sender, EventArgs e) { ProductDataSetTableAdapters.ProductTableAdapter adapter = new ProductDataSetTableAdapters.ProductTableAdapter(); ProductDataSet.ProductDataTable table = adapter.GetDataBy(1); gridResults.DataSource = table; gridResults.DataBind(); } </script> <html > <head id="Head1" runat="server"> <title>Using a Strongly Typed DataSet</title> </head> <body> <form id="form1" runat="server"> <div> <asp:GridView HeaderStyle-BackColor="Control" HeaderStyle-ForeColor="Brown" RowStyle-BackColor="Snow" runat="Server" ID="gridResults"> </asp:GridView> </div> </form> </body> </html>
This code is very simple. You create an instance of the ProductTableAdapter
, which you will use to fill the DataTable
. Notice that instead of declaring a generic DataTable
, you declare an object of type ProductDataTable
. To fill this DataTable
, you call the GetDataBy()
method and pass it a category ID. Figure 3 illustrates the result of the above code sample.
Figure 3
In addition to binding the results to the GridView
through code, you could also use an ObjectDataSource
, setting its TypeName
property to ProductDataSetTableAdapters.ProductTableAdapter
and its SelectMethod
to GetDataBy()
.
Note that strongly typed
DataSets
are not just limited to read-only scenarios. You can easily use strongly typedDataSets
for insert, update, and delete scenarios the same way you would do with untypedDataSets
.
There are additional methods to accomplish strong typing in your applications, outside of using strongly typed DataSets
. For example, you can create custom classes that are more lightweight than DataSets
and correspond exactly to your database.
Key Considerations for Strongly Typed DataSets
So far, you have seen examples demonstrating how strongly typed DataSets
make the jobs of creating and consuming DataSets
far easier. Typed DataSets
are easier to maintain, have strongly typed accessors, provide rigid data validation, and, because they can still be serialized, can be exposed as the return types of web service function calls.
It would be reasonable to ask, however, whether these things are any faster or slower than regular DataSets
. Unfortunately, the answer is far from clear. You may already know that throwing exceptions incurs a slight overhead from the runtime, as does typecasting. All of the properties and functions in a strongly typed DataSet
are wrapped in exception-handling calls, and a great many are wrapped in typecasting code. This leads some people to believe that they are slightly less efficient than standard DataSets
. However, in any production application, you’ll be wrapping your DataSet
in exception-handling and typecasting code anyway, so the fact that the typed DataSet
does this for you should be considered an advantage and not a performance drain.
Because of the inherent advantages of strongly typed DataSets
and their role in making your code easier to develop and maintain, you should consider the feasibility of using strongly typed DataSets
for your applications.
This article is adapted from Professional ASP.NET 2.0 Databases by Thiru Thangarathinam (Wrox, 2006, ISBN: 978-0-7645-9677-3), from Chapter 13, “Advanced ADO.NET for ASP.NET Data Display.”
Copyright 2007 by WROX. All rights reserved. Reproduced here by permission of the publisher.