Practical ASP.NET
Deferring Data Retrieval in Master/Detail Pages
This is one big problem that's simple to fix. Peter shows you two solutions.
It's easy to create master/detail pages in ASP.NET. But it's equally easy to
reduce your application's scalability if you implement your page naively.
When it comes to displaying data on the page, the Holy Grail that everyone
seems to want is the master/detail page: a GridView or DropDownList at the top
of the page that displays a list of choices (the "master") and a DataView
or FormView at the bottom of the page that, when a record is selected in the
master control, displays all the related records (the "detail"). Unfortunately,
most developers implement this design in a way that reduces their application's
scalability.
The problem occurs because the Page, by default, always selects a record in
the master control. As a result, a naive implementation of a master/detail page
results in the details for the first record on the Page being displayed when
the page is first requested -- before the user has had a chance to pick a record
in the master.
The naive implementation violates the first rule of scalability: Until you
know what data your user wants, you should never (never!) retrieve any data.
Retrieving data involves the two slowest things your application can do: reading
from the hard disk and making a call to an external computer -- in this case,
the database server. Unless all of your users always want to see the detail
information for the first item in the master, the naive master/details design
ensures a useless trip to the database.
And it's so easy to fix.
Delaying Data Retrieval
The reason that the details are retrieved is that the Page automatically calls
the DataBind method of all DataViews on the Page. Calling the DataBind method
of the master control fills the control with data and causes the first record
in the control to be selected. The Page then goes on to call the DataBind method
on the child control and the child control retrieves the details for the first
record in the master control.
There are two solutions to this problem. The first is to configure your child
DataView and DataSource at design time as before but then set the child DataView's
DataSourceID property to null. This effectively disconnects the DataView from
its DataSource. The Page skips over any DataViews with a null DataSourceID,
so no detail data is retrieved.
The next step in this solution is to add code so that when the user makes a
selection in the master control, the child's DataSourceID and DataSource are
"re-wired." The simplest solution is to put code behind a search button
that sets the child's DataSourceID to its related DataSource and then calls
the child's DataBind method (you could put the code in the master control's
SelectedItemChanged event but that makes it difficult for the user to retrieve
the first record in the master control). This is probably the best solution
when the master control is a GridView.
If the master control is a DropDownList or some other listing control, another
solution is to load a dummy item into the master control at design time (typically,
this item has a Text value of "Select a Customer" or the like). You
need to set the listing control's AppendDataBoundItems property to True to ensure
that the item you added at design time won't be wiped out when the listing control's
DataBind method is called.
Some code is still required: In the control's Selecting event (fired just before
data is retrieved), you need to check for the design time entry and cancel the
retrieval:
If e.Command.Parameters(0).Value = "Select a Customer" Then
e.Cancel = True
End If
There are more complicated solutions. I've seen developers have their users
enter their selection criteria on one page and then transfer those criteria
in a querystring to the page that displays the detail data. This ensures that
the user's selection is known when the detail page first displays.
Unfortunately, this design either requires the user to return to the first
page to enter new criteria or requires the developer to duplicate the master
control on both pages. It's simpler to put the whole design on one page and
defer retrieving data until after the users have made their selection.
About the Author
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.