Unboxed Solutions Blog The frenetic soapbox

Jan 21

Sean

Update: GridView Custom Paging with ObjectDataSource

  • Created: Saturday, January 21, 2006
  • Sean

About a month ago I posted some code for implementing custom paging with the GridView and ObjectDataSource with the goal being a single database call to get the records and the rowcount. The code I posted involved some hackery in that I was passing around a ObjectDataSourceSelectingEventArgs object from the Selecting event as an argument for my specified Select and SelectCount operations. The behavior for custom paging with the ObjectDataSource involves 2 calls: 1 to get the results of the select operation, and 1 to get the total number of records. What I think sucks about this is that it requires 2 different database calls - or does it? No, it doesn't. Like I said, the code I posted last month (last year too) worked around this issue, but I questioned how much of a hack it was.

I emailed Fritz Onion and asked him to take a look at it and he suggested that it was a good idea to reduce the round trips to the database and offered a much cleaner solution. Instead of including the ObjectDataSourceSelectingEventArgs to set the TotalRowCount property, he suggested simply setting a value in the HttpContext.Current.Items hashtable during the select operation and the use that value in the select count operation. This is possible because HttpContext.Current.Items is a per-request hashtable and both operations are obviously executed during the same request. Thank you Fritz!

Here is the updated code...

<asp:GridView ID="gridViewOrders" runat="server" AllowPaging="True" AutoGenerateColumns="False"

    CellPadding="4" DataSourceID="objectDataSourceOrders" ForeColor="#333333" GridLines="None">

    <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />

    <Columns>

        <asp:BoundField DataField="ProductId" HeaderText="ProductId" SortExpression="ProductId" />

        <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />

        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />

        <asp:BoundField DataField="CustomerId" HeaderText="CustomerId" SortExpression="CustomerId" />

        <asp:BoundField DataField="OrderId" HeaderText="OrderId" SortExpression="OrderId" />

        <asp:BoundField DataField="OrderDate" HeaderText="OrderDate" SortExpression="OrderDate" />

        <asp:BoundField DataField="ContactName" HeaderText="ContactName" SortExpression="ContactName" />

    </Columns>

    <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />

    <EditRowStyle BackColor="#999999" />

    <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />

    <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />

    <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />

    <AlternatingRowStyle BackColor="White" ForeColor="#284775" />

</asp:GridView>

<asp:ObjectDataSource ID="objectDataSourceOrders" runat="server" EnablePaging="True"

    SelectMethod="Select" TypeName="OrderDataSource"

    SelectCountMethod="SelectCount"></asp:ObjectDataSource>

 

//Lame, but no DAL in this example. :-)

public class OrderDataSource

{

    public OrderDataSource() { }

 

    public int SelectCount()

    {

        return (int)HttpContext.Current.Items["rowCount"];

    }

 

    public OrderCollection Select(int maximumRows, int startRowIndex)

    {

        using (SqlConnection connection = new SqlConnection("Initial Catalog=Northwind;Integrated Security=SSPI;Data Source=."))

        using (SqlCommand command = new SqlCommand("SeanPagerProc", connection))

        {

            connection.Open();

            command.CommandType = CommandType.StoredProcedure;

            command.Parameters.AddWithValue("@pagestart", startRowIndex);

            command.Parameters.AddWithValue("@pagesize", maximumRows);

            command.Parameters.Add(new SqlParameter("@numresults", SqlDbType.Int, 0, ParameterDirection.Output, false, 0, 0, null, DataRowVersion.Default, 0));

            OrderCollection orders = new OrderCollection();

 

            using (SqlDataReader reader = command.ExecuteReader())

            {

                while (reader.Read())

                {

                    Order o = new Order();

                    //missing null checks, has hard-coded column ordinals...it's all bad

                    o.ContactName = reader.GetString(2);

                    o.CustomerId = reader.GetString(1);

                    o.OrderDate = reader.GetDateTime(4);

                    o.OrderId = reader.GetInt32(3);

                    o.ProductId = reader.GetInt32(5);

                    o.ProductName = reader.GetString(6);

                    o.UnitPrice = (float)reader.GetDecimal(7);

                    orders.Add(o);

                }

            }

            HttpContext.Current.Items["rowCount"] = command.Parameters["@numresults"].Value;

            return orders;

        }

    }
}

;