ptg 804 CHAPTER 18 Using the ObjectDataSource Control When you open the page in Listing 18.20, the GridView displays its paging interface, which you can use to navigate between different pages of records (see Figure 18.5). FIGURE 18.5 Displaying multiple pages with data source paging. NOTE The paging mechanism described in this section is based on the mechanism used by the Microsoft ASP.NET forums at http://www.asp.net/forums and the XBOX forums at http://www.xbox.com. Both of these websites handle an incredible number of message posts every day. The forums software was written with ASP.NET and is available from TelligentSystems (www.telligentsystems.com) as part of their Community Server product. If temporary tables make you anxious, you have an alternative when working with Microsoft SQL Server 2005 or 2008. You can take advantage of the new ROW_NUMBER() function to select a range of rows. The ROW_NUMBER() function automatically calculates the sequential number of a row within a resultset. The modified stored procedure in Listing 18.24 does the same thing as the stored procedure in Listing 18.23. However, the modified stored procedure avoids any temporary tables. From the Library of Wow! eBook ptg 805 Paging, Sorting, and Filtering Data with the ObjectDataSource Control 18 LISTING 18.24 GetPagedMovies2005.sql CREATE PROCEDURE dbo.GetPagedMovies2005 ( @StartRowIndex INT, @MaximumRows INT ) AS WITH OrderedMovies AS ( SELECT Id, ROW_NUMBER() OVER (ORDER BY Id) AS RowNumber FROM Movies ) SELECT OrderedMovies.RowNumber, Movies.Id, Movies.Title, Movies.Director FROM OrderedMovies JOIN Movies ON OrderedMovies.Id = Movies.Id WHERE RowNumber BETWEEN (@StartRowIndex + 1) AND (@startRowIndex + @maximumRows + 1) User Interface Sorting If you need to sort the records displayed by the GridView control, the easiest type of sorting to enable is user interface sorting. When you take advantage of user interface sorting, the records are sorted in the server’s memory. For example, the page in Listing 18.25 contains a GridView that has its AllowSorting property set to the value True. The GridView is bound to an ObjectDataSource that repre- sents the Employees database table (see Figure 18.6). From the Library of Wow! eBook ptg 806 CHAPTER 18 Using the ObjectDataSource Control LISTING 18.25 ShowUISorting.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show User Interface Sorting</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:GridView id=”grdEmployees” DataSourceID=”srcEmployees” AllowSorting=”True” Runat=”server” /> <asp:ObjectDataSource id=”srcEmployees” TypeName=”EmployeesUISorting” SelectMethod=”GetEmployees” Runat=”server” /> FIGURE 18.6 Sorting records with user interface sorting. From the Library of Wow! eBook ptg 807 Paging, Sorting, and Filtering Data with the ObjectDataSource Control 18 </div> </form> </body> </html> The ObjectDataSource control in Listing 18.25 is bound to the component in Listing 18.26. The GetEmployees() method returns an ADO.NET DataSet object. When taking advantage of user interface sorting, the ObjectDataSource control must represent the right type of data source. The right type of data source includes DataSet, DataTable, and DataView controls. LISTING 18.26 EmployeesUISorting.cs using System; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; public class EmployeesUISorting { private static readonly string _conString; public static DataSet GetEmployees() { // Initialize ADO.NET objects string selectText = “SELECT Id,FirstName,LastName,Phone FROM Employees”; SqlDataAdapter dad = new SqlDataAdapter(selectText, _conString); DataSet dstEmployees = new DataSet(); // Fill the DataSet using (dad) { dad.Fill(dstEmployees); } return dstEmployees; } static EmployeesUISorting() { _conString = ➥ WebConfigurationManager.ConnectionStrings[“Employees”].ConnectionString; } } From the Library of Wow! eBook ptg 808 CHAPTER 18 Using the ObjectDataSource Control User interface sorting is convenient. You can enable this type of sorting by setting a single property of the GridView control. Unfortunately, just as with user interface paging, some serious performance drawbacks result from user interface sorting. All the records from the underlying database must be loaded and sorted in memory. This is a particular problem when you want to enable both sorting and paging at the same time. In the next section, you learn how to implement data source sorting, which avoids this performance issue. Data Source Sorting Imagine that you are working with a database table that contains 3 billion records and you want to enable users to both sort the records and page through the records contained in this table. In that case, you want to implement both data source sorting and paging. The page in Listing 18.27 contains a GridView and ObjectDataSource control. The GridView has both its AllowSorting and AllowPaging properties enabled (see Figure 18.7). FIGURE 18.7 Paging and sorting database records. LISTING 18.27 ShowDSSorting.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> From the Library of Wow! eBook ptg 809 Paging, Sorting, and Filtering Data with the ObjectDataSource Control 18 <style type=”text/css”> .employees td,.employees th { font:16px Georgia,Serif; padding:5px; } a { color:blue; } </style> <title>Show Data Source Sorting</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:GridView id=”grdEmployees” DataSourceID=”srcEmployees” AllowSorting=”true” AllowPaging=”true” PageSize=”3” CssClass=”employees” Runat=”server” /> <asp:ObjectDataSource id=”srcEmployees” TypeName=”EmployeesDSSorting” SelectMethod=”GetEmployees” SelectCountMethod=”GetEmployeeCount” EnablePaging=”true” SortParameterName=”sortExpression” Runat=”server” /> </div> </form> </body> </html> The ObjectDataSource control in Listing 18.27 represents the EmployeesDSSorting component in Listing 18.28. The ObjectDataSource control includes a SortParameterName property. When this property is present, the ObjectDataSource control uses data source sorting instead of user interface sorting. From the Library of Wow! eBook ptg 810 CHAPTER 18 Using the ObjectDataSource Control LISTING 18.28 EmployeesDSSorting.vb Imports System Imports System.Data Imports System.Data.SqlClient Imports System.Web.Configuration Public Class EmployeesDSSorting Private Shared ReadOnly _conString As String Public Shared Function GetEmployees(ByValsortExpression As String, ByVal startRowIndex As Integer, ByVal maximumRows As Integer) As SqlDataReader ‘ Initialize connection Dim con As New SqlConnection(_conString) ‘ Initialize command Dim cmd As New SqlCommand() cmd.Connection = con cmd.CommandText = “GetSortedEmployees” cmd.CommandType = CommandType.StoredProcedure ‘ Create parameters cmd.Parameters.AddWithValue(“@SortExpression”, sortExpression) cmd.Parameters.AddWithValue(“@StartRowIndex”, startRowIndex) cmd.Parameters.AddWithValue(“@MaximumRows”, maximumRows) ‘ Execute command con.Open() Return cmd.ExecuteReader(CommandBehavior.CloseConnection) End Function Public Shared Function GetEmployeeCount() As Integer Dim context As HttpContext = HttpContext.Current If context.Cache(“EmployeeCount”) Is Nothing Then context.Cache(“EmployeeCount”) = GetEmployeeCountFromDB() End If Return CType(context.Cache(“EmployeeCount”), Integer) End Function Private Shared Function GetEmployeeCountFromDB() As Integer Dim result As Integer = 0 From the Library of Wow! eBook ptg 811 Paging, Sorting, and Filtering Data with the ObjectDataSource Control 18 ‘ Initialize connection Dim con As SqlConnection = New SqlConnection(_conString) ‘ Initialize command Dim cmd As SqlCommand = New SqlCommand() cmd.Connection = con cmd.CommandText = “SELECT Count(*) FROM Employees” ‘ Execute command Using con con.Open() result = CType(cmd.ExecuteScalar(), Integer) End Using Return result End Function Shared Sub New() _conString = ➥ WebConfigurationManager.ConnectionStrings(“Employees”).ConnectionString End Sub End Class The GetEmployees() method in the component in Listing 18.28 calls a stored procedure to sort and page records. The stored procedure, named GetSortedEmployees, returns a sorted page of records from the Employees database table. This stored procedure is contained in Listing 18.29. LISTING 18.29 GetSortedEmployees.sql CREATE PROCEDURE GetSortedEmployees ( @SortExpression NVarChar(100), @StartRowIndex INT, @MaximumRows INT ) AS Create a temp table to store the select results CREATE TABLE #PageIndex ( IndexId INT IDENTITY (1, 1) NOT NULL, RecordId INT From the Library of Wow! eBook ptg 812 CHAPTER 18 Using the ObjectDataSource Control ) INSERT into the temp table INSERT INTO #PageIndex (RecordId) SELECT Id FROM Employees ORDER BY CASE WHEN @SortExpression=’Id’ THEN Id END ASC, CASE WHEN @SortExpression=’Id DESC’ THEN Id END DESC, CASE WHEN @SortExpression=’FirstName’ THEN FirstName END ASC, CASE WHEN @SortExpression=’FirstName DESC’ THEN FirstName END DESC, CASE WHEN @SortExpression=’LastName’ THEN LastName END ASC, CASE WHEN @SortExpression=’LastName DESC’ THEN LastName END DESC, CASE WHEN @SortExpression=’Phone’ THEN Phone END ASC, CASE WHEN @SortExpression=’Phone DESC’ THEN Phone END DESC Get a page of records SELECT Id, FirstName, LastName, Phone FROM Employees INNER JOIN #PageIndex WITH (nolock) ON Employees.Id = #PageIndex.RecordId WHERE #PageIndex.IndexID > @StartRowIndex AND #PageIndex.IndexID < (@StartRowIndex + @MaximumRows + 1) ORDER BY #PageIndex.IndexID The stored procedure in Listing 18.29 uses SQL CASE functions to sort the records before they are added to the temporary table. Unfortunately, you can’t use a parameter with an ORDER BY clause, so the sort columns must be hard-coded in the CASE functions. Next, a page of records is selected from the temporary table. NOTE As an alternative to the data source sorting method described in this section, you can use LINQ to SQL. For more information on LINQ to SQL, see Chapter 20. From the Library of Wow! eBook ptg 813 Paging, Sorting, and Filtering Data with the ObjectDataSource Control 18 Filtering Data You can supply the ObjectDataSource control with a filter expression. The filter expres- sion is applied to the data returned by the control’s select method. A filter is particularly useful when used in combination with caching. You can load all the data into the cache and then apply different filters to the cached data. NOTE You lear n how to cache data with the ObjectDataSource control in Chapter 29, “Caching Application Pages and Data.” For example, the page in Listing 18.30 contains a DropDownList and GridView control. The DropDownList displays a list of movie categories, and the GridView displays matching movies (see Figure 18.8). FIGURE 18.8 Filtering movies with the ObjectDataSource control. From the Library of Wow! eBook . 18.5 Displaying multiple pages with data source paging. NOTE The paging mechanism described in this section is based on the mechanism used by the Microsoft ASP. NET forums at http://www .asp. net/ forums. AllowPaging properties enabled (see Figure 18.7). FIGURE 18.7 Paging and sorting database records. LISTING 18.27 ShowDSSorting.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC -/ /W3C//DTD. <div> < ;asp: GridView id=”grdEmployees” DataSourceID=”srcEmployees” AllowSorting=”True” Runat=”server” /> < ;asp: ObjectDataSource id=”srcEmployees” TypeName=”EmployeesUISorting”