Disconnected Data Access


The ADO.NET Framework supports two models of data access. In the first part of this chapter, you saw how you can use the SqlConnection, SqlCommand, and SqlDataReader objects to connect to a database and retrieve data. When you read data from a database by using a SqlDataReader object, an open connection must be maintained between your application and the database.

In this section, we examine the second model of data access supported by ADO.NET: the disconnected model. When you use the objects discussed in this section, you do not need to keep a connection to the database open.

This section discusses four new ADO.NET objects:

  • DataAdapter Enables you to transfer data from the physical database to the in-memory database and back again.

  • DataTable Represents an in-memory database table.

  • DataView Represents an in-memory database view.

  • DataSet Represents an in-memory database.

The ADO.NET objects discussed in this section are built on top of the ADO.NET objects discussed in the previous section. For example, behind the scenes, the DataAdapter uses a DataReader to retrieve data from a database.

The advantage of using the objects discussed in this section is that they provide you with more functionality. For example, you can filter and sort the rows represented by a DataView. Furthermore, you can use the DataTable object to track changes made to records and accept or reject the changes.

The big disadvantage of using the objects discussed in this section is that they tend to be slower and more resource intensive. Retrieving 500 records with a DataReader is much faster than retrieving 500 records with a DataAdapter.

Note

For detailed performance comparisons between the DataReader and DataAdapter, see Priya Dhawan's article at the Microsoft MSDN website (msdn.Microsoft.com), entitled "Performance Comparison: Data Access Techniques."


Therefore, unless you need to use any of the specialized functionality supported by these objects, my recommendation is that you stick with the objects discussed in the first part of this chapter when accessing a database. In other words, DataReaders are good and DataAdapters are bad.

Using the DataAdapter Object

The DataAdapter acts as the bridge between an in-memory database table and a physical database table. You use the DataAdapter to retrieve data from a database and populate a DataTable. You also use a DataAdapter to push changes that you have made to a DataTable back to the physical database.

The component in Listing 16.25 illustrates how you can use a SqlDataAdapter to populate a DataTable.

Listing 16.25. App_Code\Movie8.vb

[View full width]

Imports System Imports System.Data Imports System.Data.SqlClient Imports System.Web.Configuration Imports System.Collections.Generic Public Class Movie8     Private Shared ReadOnly _connectionString As String     Public Function GetAll() As DataTable         ' Initialize the DataAdapter         Dim dad As New SqlDataAdapter("SELECT Title,Director FROM Movies", _connectionString)         ' Create a DataTable         Dim dtblMovies As New DataTable()         ' Populate the DataTable         dad.Fill(dtblMovies)         ' Return results         Return dtblMovies     End Function     Shared Sub New()         _connectionString = WebConfigurationManager.ConnectionStrings("Movies") .ConnectionString     End Sub End Class 

The page in Listing 16.26 contains a GridView that is bound to an ObjectDataSource that represents the component in Listing 16.25 (see Figure 16.12).

Figure 16.12. Displaying data with a DataAdapter.


Listing 16.26. ShowMovie8.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show Movie8</title> </head> <body>     <form  runat="server">     <div>     <asp:GridView                  DataSource         Runat="server" />      <asp:ObjectDataSource                  TypeName="Movie8"         SelectMethod="GetAll"         Runat="server" />     </div>     </form> </body> </html> 

Notice that a SqlConnection is never explicitly created in the component in Listing 16.25. When you call the SqlDataAdapter object's Fill() method, the SqlDataAdapter automatically creates and opens a connection. After the data is fetched from the database, the Fill() method automatically closes the connection.

You don't need to wrap the call to the Fill() method within a Using or try...Catch statement. Internally, the SqlDataAdapter uses a try...Catch statement to ensure that its connection gets closed.

Opening and closing a database connection is a slow operation. If you know that you will need to perform another database operation after using the SqlDataAdapter, then you should explicitly create a SqlConnection and open it like this:

Dim con As New SqlConnection(...connection string...) Dim dad As New SqlDataAdapter("SELECT Title,Director FROM Movies", con) Using con   con.Open()   dad.Fill(dtblMovies)   ... Perform other database operations with connection ... End Using 


If a SqlConnection is already open when you call the Fill() method, the Fill() method doesn't close it. In other words, the Fill() method maintains the state of the connection.

Performing Batch Updates

You can think of a SqlDataAdapter as a collection of four SqlCommand objects:

  • SelectCommand Represents a SqlCommand used for selecting data from a database.

  • UpdateCommand Represents a SqlCommand used for updating data in a database.

  • InsertCommand Represents a SqlCommand used for inserting data into a database.

  • DeleteCommand Represents a SqlCommand used for deleting data from a database.

You can use a DataAdapter not only when retrieving data from a database. You can also use a DataAdapter when updating, inserting, and deleting data from a database.

If you call a SqlDataAdapter object's Update() method, and pass the method a DataTable, then the SqlDataAdapter calls its UpdateCommand, InsertCommand, and DeleteCommand to make changes to the database.

You can assign a SqlCommand object to each of the four properties of the SqlDataAdapter. Alternatively, you can use the SqlCommandBuilder object to create the UpdateCommand, InsertCommand, and DeleteCommand for you. The SqlCommandBuilder class takes a SqlDataAdapter that has a SELECT command and generates the other three commands automatically.

For example, the page in Listing 16.27 displays all the records from the Movies database table in a spreadsheet created with a Repeater control (see Figure 16.13). If you make changes to the data and click the Update button, then the Movies database table is updated with the changes.

Figure 16.13. Batch updating database records.


Listing 16.27. ShowDataAdapterUpdate.aspx

[View full width]

<%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Private dad As SqlDataAdapter     Private dtblMovies As DataTable     Sub Page_Load()         ' Create connection         Dim connectionString As String = WebConfigurationManager.ConnectionStrings ("Movies").ConnectionString         Dim con As New SqlConnection(connectionString)         ' Create Select command         dad = New SqlDataAdapter("SELECT Id,Title,Director FROM Movies", con)         ' Create Update, Insert, and Delete commands with SqlCommandBuilder         Dim builder As New SqlCommandBuilder(dad)         ' Add data to DataTable         dtblMovies = New DataTable()         dad.Fill(dtblMovies)         ' Bind data to Repeater         rptMovies.DataSource = dtblMovies         rptMovies.DataBind()     End Sub     Protected  Sub lnkUpdate_Click(ByVal sender As Object, ByVal e As EventArgs)         ' Update DataTable with changes         For  i as integer = 0 To rptMovies.Items.Count- 1             Dim item As RepeaterItem =  rptMovies.Items(i)             Dim txtTitle As TextBox = CType(item.FindControl("txtTitle"), TextBox)             Dim txtDirector As TextBox = CType(item.FindControl("txtDirector"), TextBox)             If dtblMovies.Rows(i)("Title") <> txtTitle.Text Then                 dtblMovies.Rows(i)("Title") = txtTitle.Text             End If             If dtblMovies.Rows(i)("Director") <> txtDirector.Text Then                 dtblMovies.Rows(i)("Director") = txtDirector.Text             End If         Next         ' Set batch size to maximum size         dad.UpdateBatchSize = 0         ' Perform update         Dim numUpdated As Integer = dad.Update(dtblMovies)         lblResults.Text = String.Format("Updated {0} rows", numUpdated)     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show DataAdapter Update</title> </head> <body>     <form  runat="server">     <div>     <asp:Repeater                  EnableViewState="false"         Runat="server">         <HeaderTemplate>         <table>         <tr>             <th>Title</th><th>Director</th>         </tr>         </HeaderTemplate>         <ItemTemplate>         <tr>         <td>         <asp:TextBox                          Text='<%#Eval("Title")%>'             Runat="server" />         </td>         <td>         <asp:TextBox                          Text='<%#Eval("Director")%>'             Runat="server" />         </td>         </tr>         </ItemTemplate>         <FooterTemplate>         </table>         </FooterTemplate>     </asp:Repeater>     <br />     <asp:LinkButton                  Text="Update Movies"         Runat="server" OnClick="lnkUpdate_Click" />     <br /><br />     <asp:Label                  EnableViewState="false"         Runat="server" />     </div>     </form> </body> </html> 

The SqlDataAdapter in Listing 16.27 performs a batch update. When a SqlDataAdapter object's UpdateBatchSize property is set to the value 0, the SqlDataAdapter performs all its updates in a single batch. If you want to perform updates in smaller batches, then you can set the UpdateBatchSize to a particular size.

Note

Performing batch updates is a new feature of ADO.NET 2.0.


Using the DataTable Object

The DataTable object represents an in-memory database table. You can add rows to a DataTable with a SqlDataAdapter, with a SqlDataReader, with an XML file, or programmatically.

For example, the page in Listing 16.28 builds a new DataTable programmatically. The contents of the DataTable are then displayed in a GridView control (see Figure 16.14).

Figure 16.14. Displaying a DataTable that was built programmatically.


Listing 16.28. ShowDataTableProgram.aspx

<%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub Page_Load()         ' Create the DataTable columns         Dim NewDataTable As New DataTable()         NewDataTable.Columns.Add("Id", GetType(Integer))         NewDataTable.Columns.Add("ProductName", GetType(String))         NewDataTable.Columns.Add("ProductPrice", GetType(Decimal))         ' Mark the Id column as an autoincrement column         NewDataTable.Columns("Id").AutoIncrement = True         ' Add some data rows         For i As Integer = 1 To 10             Dim NewRow As DataRow = NewDataTable.NewRow()             NewRow("ProductName") = "Product " & i.ToString()             NewRow("ProductPrice") = 12.34             NewDataTable.Rows.Add(NewRow)         Next         ' Bind DataTable to GridView         grdProducts.DataSource = NewDataTable         grdProducts.DataBind()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show DataTable Programmatically</title> </head> <body>     <form  runat="server">     <div>     <h1>Products</h1>     <asp:GridView                  Runat="server" />     </div>     </form> </body> </html> 

In Listing 16.28, a DataTable with the following three columns is created: Id, ProductName, and ProductPrice. The data type of each column is specified with a .NET Framework type. For example, the ProductPrice column is created as a decimal column. Alternatively, you could create each column with a SqlType. For example, you could use System.Data.SqlTypes.SqlDecimal for the type of the ProductPrice column.

Notice that the Id column is created as an autoincrement column. When you add new rows to the DataTable, the column increments its value automatically.

Selecting DataRows

You can retrieve particular rows from a DataTable by using the DataTable object's Select() method. The Select() method accepts a filter parameter. You can use just about anything that you would use in a SQL WHERE clause with the filter parameter.

When you retrieve an array of rows with the Select() method, you can also specify a sort order for the rows. When specifying a sort order, you can use any expression that you would use with a SQL ORDER BY clause.

For example, the page in Listing 16.29 caches a DataTable in memory with the ASP.NET Cache object. The page contains a TextBox control. When you enter a partial movie title into the TextBox control, a list of matching movies is displayed in a GridView control. The rows are sorted in order of the movie title (see Figure 16.15).

Figure 16.15. Selecting matching rows from a cached DataTable.


Listing 16.29. ShowDataTableSelect.aspx

[View full width]

<%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Protected Sub btnSearch_Click(ByVal sender As Object, ByVal e As EventArgs)         ' Get movies DataTable from Cache         Dim dtblMovies As DataTable = CType(Cache("MoviesToFilter"), DataTable)         If IsNothing(dtblMovies) Then             dtblMovies = GetMoviesFromDB()             Cache("MoviesToFilter") = dtblMovies         End If         ' Select matching rows         Dim filter As String = String.Format("Title LIKE '{0}*'", txtTitle.Text)         Dim rows() As DataRow = dtblMovies.Select(filter, "Title")         ' Bind to GridView         grdMovies.DataSource = rows         grdMovies.DataBind()     End Sub     Private Function GetMoviesFromDB() As DataTable         Dim connectionString As String = WebConfigurationManager.ConnectionStrings ("Movies").ConnectionString         Dim dad As New SqlDataAdapter("SELECT Title, Director FROM Movies", connectionString)         Dim dtblMovies As New DataTable()         dad.Fill(dtblMovies)         Return dtblMovies     End Function </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <style type="text/css">         th, td         {             padding:5px;         }     </style>     <title>Show DataTable Select</title> </head> <body>     <form  runat="server">     <div>     <asp:TextBox                  Tooltip="Search"         Runat="server" />     <asp:Button                  Text="Search"         Runat="server" OnClick="btnSearch_Click" />     <hr />     <asp:GridView                  AutoGenerateColumns="false"         Runat="server">         <Columns>         <asp:TemplateField HeaderText="Title">         <ItemTemplate>             <%# CType(Container.DataItem,DataRow)("Title") %>         </ItemTemplate>         </asp:TemplateField>         <asp:TemplateField HeaderText="Director">         <ItemTemplate>             <%#CType(Container.DataItem, DataRow)("Director")%>         </ItemTemplate>         </asp:TemplateField>         </Columns>         </asp:GridView>     </div>     </form> </body> </html> 

The DataTable Select() method returns an array of DataRow objects. Notice that there is nothing wrong with binding an array of DataRow objects to a GridView control. However, you must explicitly cast each data item to a DataRow and read within a GridView TemplateField.

DataRow States and DataRow Versions

When you modify the rows in a DataTable, the DataTable keeps track of the changes that you make. A DataTable maintains both the original and modified version of each row.

Each row in a DataTable has a particular RowState that has one of the following values:

  • Unchanged The row has not been changed.

  • Added The row has been added.

  • Modified The row has been modified.

  • Deleted The row has been deleted.

  • Detached The row has been created but not added to the DataTable.

Each row in a DataTable can have more than one version. Each version is represented by one of the following values of the DataRowVersion enumeration:

  • Current The current version of the row.

  • Default The default version of the row.

  • Original The original version of the row.

  • Proposed The version of a row that exists during editing.

You can use the DataTable.AcceptChanges() method to copy the current versions of all the rows to the original versions of all the rows. And you can use the DataTable.RejectChanges() method to copy the original versions of all the rows to the current versions of all the rows.

For example, the component in Listing 16.30 includes an AcceptChanges() and RejectChanges() method. The component maintains a DataTable in Session state. If you update a row in the DataTable, the row is updated in memory. If the RejectChanges() method is called, any changes made to the DataTable are rejected. If the AcceptChanges() method is called, the database is updated and all changes are accepted.

Listing 16.30. App_Code\Movie9.vb

[View full width]

Imports System Imports System.Data Imports System.Data.SqlClient Imports System.Web Imports System.Web.Configuration Public Class Movie9     Private dad As New SqlDataAdapter()     Public Function GetAll() As DataTable         Return CType(HttpContext.Current.Session("MoviesToEdit"), DataTable)     End Function     Public Sub Update(ByVal id As Integer, ByVal title As String, ByVal director As String)         Dim movies As DataTable = CType(HttpContext.Current.Session("MoviestoEdit"),  DataTable)         Dim rowToEdit As DataRow = movies.Rows.Find(id)         rowToEdit("title") = title         rowToEdit("director") = director     End Sub     Public Sub RejectChanges()         Dim movies As DataTable = CType(HttpContext.Current.Session("MoviestoEdit"),  DataTable)         movies.RejectChanges()     End Sub     Public Sub AcceptChanges()         Dim movies As DataTable = CType(HttpContext.Current.Session("MoviestoEdit"),  DataTable)         dad.Update(movies)         movies.AcceptChanges()     End Sub     Public Sub New()         ' Create Data Adapter         Dim connectionString As String = WebConfigurationManager.ConnectionStrings ("Movies").ConnectionString         dad = New SqlDataAdapter("SELECT Id,Title,Director FROM Movies", connectionString)         Dim builder As New SqlCommandBuilder(dad)         dad.UpdateBatchSize = 0         Dim context As HttpContext = HttpContext.Current         If IsNothing(context.Session("MoviesToEdit")) Then             ' Add data to DataTable             Dim dtblMovies As New DataTable()             dad.Fill(dtblMovies)             dtblMovies.PrimaryKey = New DataColumn() {dtblMovies.Columns("Id")}             context.Session("MoviesToEdit") = dtblMovies         End If     End Sub End Class 

The page in Listing 16.31 contains a GridView that is bound to the component in Listing 16.30. The GridView includes a column that indicates whether each row has been changed. The column displays the value of the corresponding DataRow object's RowState property (see Figure 16.16).

Listing 16.31. ShowMovie9.aspx

<%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Protected Sub btnReject_Click(ByVal sender As Object, ByVal e As EventArgs)         Dim movie As New Movie9()         movie.RejectChanges()         grdMovies.DataBind()     End Sub     Protected Sub btnAccept_Click(ByVal sender As Object, ByVal e As EventArgs)         Dim movie As New Movie9()         movie.AcceptChanges()         grdMovies.DataBind()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show Movie9</title> </head> <body>     <form  runat="server">     <div>     <h1>Edit Movies</h1>     <asp:GridView                  DataSource         DataKeyNames="Id"         AutoGenerateEditButton="true"         Runat="server">         <Columns>         <asp:TemplateField>         <ItemTemplate>         <%#CType(Container.DataItem, DataRowView).Row.RowState.ToString()%>         </ItemTemplate>         </asp:TemplateField>         </Columns>     </asp:GridView>     <br />     <asp:Button                  Text="Reject Changes"         OnClick="btnReject_Click"         Runat="server" />     <asp:Button                  Text="Accept Changes"         OnClick="btnAccept_Click"         Runat="server" />     <asp:ObjectDataSource                  TypeName="Movie9"         SelectMethod="GetAll"         UpdateMethod="Update"         Runat="server" />     </div>     </form> </body> </html> 

Figure 16.16. Tracking data row changes.


If you click the Accept Changes button, all the changes made to the rows in the GridView are sent to the database. If you click the Reject Changes button, all the rows revert to their original values.

Using the DataView Object

The DataView object represents an in-memory database view. You can use a DataView object to create a sortable, filterable view of a DataTable.

The DataView object supports three important properties:

  • Sort Enables you to sort the rows represented by the DataView.

  • RowFilter Enables you to filter the rows represented by the DataView.

  • RowStateFilter Enables you to filter the rows represented by the DataView according to the row state (for example, OriginalRows, CurrentRows, Unchanged).

The easiest way to create a new DataView is to use the DefaultView property exposed by the DataTable class like this:

Dim dataView1 As DataView = dataTable1.DefaultView; 


The DefaultView property returns an unsorted, unfiltered view of the data contained in a DataTable.

You also can directly instantiate a new DataView object by passing a DataTable, filter, sort order, and DataViewRowState filter to the DataView object's constructor, like this:

Dim dataView1 As New DataView(dataTable1, _     "BoxOfficeTotals > 100000", _     "Title ASC", _     DataViewRowState.CurrentRows) 


This statement creates a new DataView from a DataTable that represents the Movies database table. The rows are filtered to include only the movies that have a box office total greater than 100,000 dollars. Also, the rows are sorted by the movie title in ascending order. Finally, all the current rows are represented from the DataTable (as opposed, for instance, to rows that have been deleted).

The page in Listing 16.30 illustrates one way that you can use a DataView. In Listing 16.32, a DataView is cached in Session state. You can sort the cached DataView by clicking on the header links rendered by the GridView control (see Figure 16.17).

Listing 16.32. ShowDataView.aspx

[View full width]

<%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub Page_Load()         If IsNothing(Session("MoviesToSort")) Then             Dim connectionString As String = WebConfigurationManager.ConnectionStrings( "Movies").ConnectionString             Dim dad As New SqlDataAdapter("SELECT Id,Title,Director FROM Movies",  connectionString)             Dim dtblMovies As New DataTable()             dad.Fill(dtblMovies)             Session("MoviesToSort") = dtblMovies.DefaultView         End If         If Not Page.IsPostBack Then             BindMovies()         End If     End Sub     Private  Sub BindMovies()         grdMovies.DataSource = Session("MoviesToSort")         grdMovies.DataBind()     End Sub     Protected  Sub grdMovies_Sorting(ByVal sender As Object, ByVal e As GridViewSortEventArgs)         Dim dvwMovies As DataView = CType(Session("MoviesToSort"), DataView)         dvwMovies.Sort = e.SortExpression         BindMovies()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show DataView</title> </head> <body>     <form  runat="server">     <div>     <asp:GridView                  AllowSorting="true"         OnSorting="grdMovies_Sorting"         Runat="server" />     </div>     </form> </body> </html> 

Figure 16.17. Sorting a cached DataView.


Using the DataSet Object

The DataSet object represents an in-memory database. A single DataSet can contain one or many DataTable objects. You can define parent/child relationships between the DataTable objects contained in a DataSet.

For example, the page in Listing 16.33 contains a treeView control. The TReeView displays a list of movie categories and, beneath each movie category, a list of matching movies (see Figure 16.18).

Listing 16.33. ShowDataSet.aspx

[View full width]

<%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Private Sub Page_Load()         If Not Page.IsPostBack Then             BuildTree()         End If     End Sub     Sub BuildTree()         ' Create Connection         Dim connectionString As String = WebConfigurationManager.ConnectionStrings ("Movies").ConnectionString         Dim con As New SqlConnection(connectionString)         ' Create Movie Categories DataAdapter         Dim dadCategories As New SqlDataAdapter("SELECT Id,Name FROM MovieCategories", con)         ' Create Movies DataAdapter         Dim dadMovies As New SqlDataAdapter("SELECT Title,CategoryId FROM Movies", con)         ' Add the DataTables to the DataSet         Dim dstMovies As New DataSet()         Using con             con.Open()             dadCategories.Fill(dstMovies, "Categories")             dadMovies.Fill(dstMovies, "Movies")         End Using         ' Add a DataRelation         dstMovies.Relations.Add("Children",dstMovies.Tables("Categories").Columns("Id") ,dstMovies.Tables("Movies").Columns("CategoryId"))         ' Add the Movie Category nodes         For Each categoryRow As DataRow In dstMovies.Tables("Categories").Rows             Dim name As String = CType(categoryRow("Name"), String)             Dim catNode As New TreeNode(name)             TreeView1.Nodes.Add(catNode)             ' Get matching movies             Dim movieRows() As DataRow = categoryRow.GetChildRows("Children")             For Each movieRow As DataRow In movieRows                 Dim title As String = CType(movieRow("Title"), String)                 Dim movieNode As New TreeNode(title)                 catNode.ChildNodes.Add(movieNode)             Next         Next     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show DataSet</title> </head> <body>     <form  runat="server">     <div>     <asp:TreeView                  Runat="server" />     </div>     </form> </body> </html> 

Figure 16.18. Building a treeView from a DataSet.


The treeView is built programmatically. In the BuildTree() method, a DataSet is created that contains two DataTable objects. The first DataTable represents the MovieCategories database table and the second DataTable represents the Movies database table. A parent/child relationship is created between the two DataTable objects with the help of a DataRelation.

The DataRelation is used to get the movies that match each movie category. The DataRow.GetChildRows() method is called to retrieve the movies that match a particular movie category.




ASP. NET 2.0 Unleashed
ASP.NET 2.0 Unleashed
ISBN: 0672328232
EAN: 2147483647
Year: 2006
Pages: 276

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net