ASP.NET
Database Operations
Sorting with Repeater
For this example, records from the Productstable are sorted prior to their display in theRepeater.
Sorting is triggered by clicking a button thatserves as the column heading. That is, whenthe "Name" button is clicked records areshown in ascending alphabetic order byproduct name; when the "Type" button isclicked, the records are ordered alphabeticallyby product type.
Sorting with Repeater
<div class="head">Sorted Product Listing - _Repeater</div>
<asp:Repeater id="RepeaterDisplay" runat="server">
<HeaderTemplate>
<table id="RepeaterTable" border="1" _style="background-color:#F9F9F9">
<tr> <th>
<asp:Button Text="Number" runat="server" _OnCommand="SortRepeater" _CommandName="ItemNumber" _EnableViewState="False"/> </th>
Sorting with Repeater
Using Button Command Properties: When the "Number"button is clicked the OnCommand event handler calls theSortRepeater subprogram. An identifier, ItemNumber in this case,is also passed to the subprogram through the CommandNameproperty.
<asp:Button Text="Number" runat="server" _OnCommand="SortRepeater " _
CommandName="ItemNumber" _
EnableViewState="False"/>
Thus, the called subprogram receives a CommandName valuethat identifies the name of a field in the Products table on whichsorting is to take place. Each of the buttons in the header rowcalls the same subprogram but names a different database fieldfor sorting.
Sorting with Repeater
An EnableViewState="False" property setting is madefor the buttons. This ensures that the visual status of abutton is not maintained in View State.
A clicked button is "highlighted" with a bolder borderthan other buttons. Unless this emphasis is turn offbetween page postings, previous buttons that wereclicked remain highlighted, making it difficult to tellwhich button was most recently clicked.
This setting does not affect actual sorting of therecords; it only affects the button's displaycharacteristics.
Sorting with Repeater
The Sort Subprogram. Record sorting takes place inthe SortRepeater subprogram. Sorting requires nomore than an SQL statement to retrieve records fromthe Products table in a particular order. That order isgiven by the CommandName argument passed to thesubprogram by a button click.
Sub SortRepeater (Src As Object, Args As _CommandEventArgs)
SQLString = "SELECT * FROM Products _
ORDER BY " & _
Args.CommandName
DisplayRepeater
End Sub
Sorting with Repeater
Notice the signature for the subprogram includes ArgsAs CommandEventArgs. CommandEventArgs is theobject through which database fields names arepassed to the subprogram.
Args.CommandName is the property containing thename of the sort field that is passed. Therefore, thisproperty is appended to a SELECT statement to returna recordset ordered by the values in that field.
This single subprogram, then, can compose a properSELECT statement for any of the buttons that areclicked.
Sorting with Repeater
Issuing the SELECT Statement. Once a proper SELECT statement isprepared a "general-purpose" DisplayRepeater subprogram can becalled to retrieve the recordset and rebind it to the Repeater.
Sub DisplayRepeater
DBConnection = New OleDbConnection( _"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")DBConnection.Open()
DBCommand = New OleDbCommand(SQLString, DBConnection)DBReader = DBCommand.ExecuteReader()
RepeaterDisplay.DataSource = DBReader
RepeaterDisplay.DataBind() DBReader.Close()
DBConnection.Close()
End Sub
In previous examples a SELECT statement was included in the databaseretrieval and binding routine. In this case the statement is composed in adifferent subprogram and just being issued in this routine.
Sorting with Repeater
Page Loading. All that remains is to code thePage_Load portion of the page. The Repeaterappears when the page loads, so an initial SQLstatement needs to be issued to populate theRepeater this first time; subsequently it is redisplayedby the sort routine.
Sub Page_Load
If Not Page.IsPostBack Then
SQLString = "SELECT * FROM Products _
ORDER BY ItemNumber“
DisplayRepeater
End If
End Sub
SortRepeater.aspx
Sorting with Repeater
On initial page load the SQLString retrieves arecordset sorted by ItemNumbers (any field could bechosen or none at all). Then the DisplayRepeatersubprogram is called to extract and bind this initialrecordset to the Repeater.
You might note that the DisplayRepeater subprogramdoes not have a signature source and argument list.This is because no arguments are being passed to it.It is not being called by a server control; it is "our"subprogram to do with as we please.
Also, since variable SQLString is referenced in twodifferent subprograms (SortRepeater andDisplayRepeater) it needs to be declared as a globalvariable.
DataGrid
FullDataGrid.aspx
Sorting with DataGrid Control
An asp:DataGrid control can automatically use itscolumn headings as links to sort routines. Minorchanges are required to the control, and similarsubprograms to the Repeater are needed.
Using Link Command Properties: First, "permission"to sort the grid is provided by addingAllowSorting="True" andOnSortCommand="SortDataGrid" to the control'sproperty list, the latter naming the subprogram to callwhen a link is clicked. Then, for those columns onwhich sorting is to take place, a SortExpression="sortfield" property is added.
Sorting with DataGrid Control
<div class="head">Sorted Product Listing - DataGrid</div>
<asp:DataGrid id="DataGridDisplay" runat="server" _AutoGenerateColumns="False" AllowSorting="True" _OnSortCommand="SortDataGrid" Width="560" _BackColor="#F9F9F9" HeaderStyle-BackColor="#990000" _HeaderStyle-ForeColor="#FFFFFF" HeaderStyle-Font- _Bold="True" HeaderStyle-HorizontalAlign="Center" ItemStyle- _VerticalAlign="Top">
<Columns>
<asp:BoundColumn
DataField="ItemNumber"
SortExpression="ItemNumber"
HeaderText="No"
HeaderStyle-Font-Size="8pt"
ItemStyle-Font-Size="8pt"/>
Sorting with DataGrid Control
<asp:TemplateColumn>
<HeaderTemplate> Description </HeaderTemplate>
<ItemTemplate>
<div class="box"> <%# Container.DataItem("ItemDescription") %>
</div>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn
DataField="ItemPrice"
SortExpression="ItemPrice"
HeaderText="Price"
HeaderStyle-Font-Size="8pt"
ItemStyle-Font-Size="8pt"
ItemStyle-HorizontalAlign="Right"/>
Sorting with DataGrid Control
<asp:BoundColumn
DataField="ItemQuantity“
SortExpression="ItemQuantity"
HeaderText="Qty"
HeaderStyle-Font-Size="8pt"
ItemStyle-Font-Size="8pt"
ItemStyle-HorizontalAlign="Right"/>
<asp:TemplateColumn>
<HeaderTemplate> Picture </HeaderTemplate>
<ItemTemplate>
<img src="Pictures/<%#Container.DataItem("ItemNumber")%> _
.jpg" style="height:50px; cursor:hand" title="Click for larger image" _onClick="ShowPicture('<%# _container.DataItem("ItemNumber")%>.jpg')"/>
</ItemTemplate> </asp:TemplateColumn>
</Columns> </asp:DataGrid>
Sorting with DataGrid Control
The Sort Subprogram. The SortDataGridsubprogram has a slightly different signature from theone used for the Repeater; plus, Args.SortExpressionidentifies the sort field passed through the link click.
Sub SortDataGrid (Src As Object, Args As _DataGridSortCommandEventArgs)
SQLString = "SELECT * FROM Products _
ORDER BY " & Args.SortExpression
DisplayDataGrid
End Sub
A SELECT statement is composed by appending thepassed field name; then subprogram DisplayDataGridis called.
Sorting with DataGrid Control
Issuing the SELECT Statement. Once a SELECT statement iscomposed, subprogram DisplayDataGrid is called to retrieve therecordset and bind it to the DataGrid. This subprogram is identical to theone used for the Repeater except for the binding statements.
Sub DisplayDataGrid
DBConnection = New OleDbConnection( _"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb") DBConnection.Open()
DBCommand = New OleDbCommand(SQLString, DBConnection)
DBReader = DBCommand.ExecuteReader()DataGridDisplay.DataSource = DBReaderDataGridDisplay.DataBind()
DBReader.Close()
DBConnection.Close()
End Sub
Sorting with DataGrid Control
Page Loading. As is done for the Repeater, an initial SQLcommand is composed and issued through the DisplayDataGridsubprogram so that the DataGrid is initially populated withrecords when the page first opens.
Sub Page_Load
If Not Page.IsPostBack Then
SQLString = "SELECT * FROM Products _
ORDER BY ItemNumber"
DisplayRepeater
DisplayDataGrid
End If
End Sub
Since variable SQLString is referenced in two differentsubprograms (SortDataGrid and DisplayDataGrid) it needs to bedeclared as a global variable.
SortDataGrid.aspx
DataList
FullDataList.aspx
Sorting with DataList Control
The asp:DataList control does not have a built-insorting feature. Radio buttons are added to select asort field and to indicate ascending or descendingsequence.
A button is added to call the SortDataList subprogram.
Coding Sort Buttons: A table to format the radiobuttons is added immediately below the caption for theDataList. The first set of buttons permits choice of asort field; the second set is for choosing the directionof sort.
A standard button calls the SortDataList subprogram.
Sorting with DataList Control
<div class="head">Sorted Product Listing - DataList</div>
<table border="1" width="560" style="border-collapse:collapse">
<tr valign="bottom"> <td> <b> Order By: </b><br>
 <asp:RadioButtonList id="SortButtons" runat="server" _RepeatDirection="Horizontal" RepeatLayout="Flow">
<asp:ListItem Text="Number " Value="ItemNumber" Selected="True"/>
...
<asp:ListItem Text="Quantity " Value="ItemQuantity"/>
</asp:RadioButtonList> </td>
<td> <b>Direction: </b><br>
<asp:RadioButtonList id="DirectionButtons" runat="server" _RepeatDirection="Horizontal" RepeatLayout="Flow">
<asp:ListItem Text="ASC" Value="ASC" Selected="True"/>
<asp:ListItem Text="DESC" Value="DESC"/>
</asp:RadioButtonList> </td>
<td> <asp:Button Text="Sort" OnClick="SortDataList" runat="server"/> </td>
</tr> </table>
Sorting with DataList Control
<asp:DataList id="DataListDisplay" runat="server" _
Width="560" _
CellSpacing="3" _
CellPadding="5" _
RepeatColumns="2" _
RepeatDirection="Horizontal" _
GridLines="Both" ItemStyle- _
BackColor="#F9F9F9" _
ItemStyle-Font-Size="8pt">
Sorting with DataList Control
<ItemTemplate>
<img src="Pictures/<%#Container.DataItem("ItemNumber")%> _
.jpg" style="width:50px; float:left; margin-right:15px; _
margin-bottom:20px; cursor:hand" _
title="Click for larger image" onClick="ShowPicture('<%# _Container.DataItem("ItemNumber")%>.jpg')"/>
<b>Number: </b><%# Container.DataItem("ItemNumber") %><br>
<b>Quantity:</b><%# Container.DataItem("ItemQuantity") %> <br><b>Description: </b><br>
<div style="width:260px; height:55px; overflow:auto">
<%# Container.DataItem("ItemDescription") %> </div>
</ItemTemplate> </asp:DataList>
Sorting with DataList Control
Coding the Sort Routine: As in previous examplesthe SortDataList subprogram creates an SQLstatement that can be executed by the DisplayDataListroutine.
In this case two values are appended to the statement.The field name is given by the value of the checkedradio button in the first set; the value ASC or DESC isgiven by the second set.
The resulting SQL statement is in the format:
SELECT * FROM Products _
ORDER BY 'field' ASC (or DESC).
Sorting with DataList Control
Sub SortDataList (Src As Object, Args As EventArgs)
SQLString = "SELECT * FROM Products _
ORDER BY " & _ SortButtons.SelectedItem.Value _
& " " & _ DirectionButtons.SelectedItem.Value
DisplayDataList
End Sub
Sub DisplayDataList
DBConnection = New OleDbConnection( _"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
DBCommand = New OleDbCommand(SQLString, DBConnection)
DBReader = DBCommand.ExecuteReader()
DataListDisplay.DataSource = DBReader
DataListDisplay.DataBind()
DBReader.Close()
DBConnection.Close()
End Sub
Sorting with DataList Control
An initial SQL command is composed and issued through theDisplayDataList subprogram when the page first opens.
Sub Page_Load
If Not Page.IsPostBack Then
SQLString = "SELECT * FROM Products _
ORDER BY ItemNumber"
DisplayDataList
End If
End Sub
Since variable SQLString is referenced in two differentsubprograms (SortDataList and DisplayDataList) it needs to bedeclared as a global variable.
SortDataList.aspx
Display Selected Records
When displaying records from a database table it isoften convenient to be able to select particular recordsfor display. This involves specifying some criterionvalue for one of the fields and then extracting onlythose records which meet that criterion; for example,select only those records where the quantity in stock isgreater than 100.
The following Repeater is based on the previouscontrol which permits record sorting. Selections areprovided to choose subsets of records from theProducts table which meet specified search criteria.For instance, the following subset shows all softwarefor which the ItemType field equals "Database", sortedin ascending sequence by ItemPrice.
Display Selected Records
In order to make the selection and sorting an SQLstatement must be composed to read
SELECT * FROM Products WHEREItemType='Database' ORDER BY ItemPrice ASC
Additional controls are added to the Repeater tocollect information to create this statement. A drop-down list permits selection of a field name, a seconddrop-down list selects a conditional operator, and atextbox provides the value for comparison. Thesethree controls permit creation of an SQL WHEREclause giving the criterion for selecting records fromthe Products table. A set of radio buttons is also addedto specify their sort order.
Display Selected Records
<div class="head">
Selected Product Listing - Repeater</div>
<asp:Panel id="FieldPanel" BackColor="#F0F0F0" Width="560" _
runat="server">
<b> Select Field: </b>
<asp:DropDownList id="FieldName" runat="server">
<asp:ListItem Value="ItemNumber" Text="Item Number"/><asp:ListItem Value="ItemType" Text="Item Type"/><asp:ListItem Value="ItemSupplier" Text="Item Supplier"/><asp:ListItem Value="ItemName" Text="Item Name"/><asp:ListItem Value="ItemDescription" Text="Item Description"/><asp:ListItem Value="ItemPrice" Text="Item Price"/><asp:ListItem Value="ItemQuantity" Text="Item Quantity"/>
</asp:DropDownList>
Display Selected Records
<asp:TextBox id="FieldValue" _
Text="Database" runat="server"/>
<asp:RadioButtonList id="DirectionButtons“ _
runat="server" RepeatDirection="Horizontal"  _
RepeatLayout="Flow">
<asp:ListItem Text="ASC" Value="ASC"  _
Selected="True"/>
<asp:ListItem Text="DESC" Value="DESC"/>
</asp:RadioButtonList> </asp:Panel>
Display Selected Records
<asp:Repeater id="RepeaterDisplay" _
runat="server">
<HeaderTemplate>
<table id="RepeaterTable" border="1“ _
style="background-color:#F9F9F9">
<tr> <th>
<asp:Button Text="Number" runat="server“ _
OnCommand="SortRepeater“ _
CommandName="ItemNumber" _
EnableViewState="False"/> </th>
...
</HeaderTemplate>
Display Selected Records
<ItemTemplate>
<tr>
<td class="center">
<%# Container.DataItem("ItemNumber") %></td>
<td> <div class="box">
<%# Container.DataItem("ItemDescription") %>
</div> </td>
<td class="right">
<%# Container.DataItem("ItemPrice") %>
</td>
</tr>
</ItemTemplate>
Display Selected Records
Field name selection is made through an asp:DropDownListsupplying field names in the Products table. The actual namesare given in the Value properties.
<b>Select Field: </b>
<asp:DropDownList id="FieldName" runat="server">
<asp:ListItem Value="ItemNumber" Text="Item Number"/>
<asp:ListItem Value="ItemType" Text="Item Type"/>
<asp:ListItem Value="ItemSupplier" Text="Item Supplier"/>
<asp:ListItem Value="ItemName" Text="Item Name"/>
<asp:ListItem Value="ItemDescription" Text="Item Description"/>
<asp:ListItem Value="ItemPrice" Text="Item Price"/>
<asp:ListItem Value="ItemQuantity" Text="Item Quantity"/>
</asp:DropDownList>
Display Selected Records
Conditional operators are selected from a second DropDownListwhose Values are the actual conditional operators and whoseText properties are verbal equivalents.
<asp:DropDownList id="Operator" runat="server">
<asp:ListItem Value=" LIKE " Text="Contains"/>
<asp:ListItem Value=" Not LIKE " Text="Does Not Contain"/>
<asp:ListItem Value=" < " Text="Less Than"/>
<asp:ListItem Value=" = " Text="Equal To"/>
<asp:ListItem Value=" > " Text="Greater Than"/>
<asp:ListItem Value=" <> " Text="Not Equal To"/>
</asp:DropDownList>
Finally, the search criterion is given in an asp:TextBox control.Values applied to SQL statements are not case sensitive, soeither lower-case, upper-case, or mixed-case characters can beentered.
<asp:TextBox id="FieldValue" Text="Database" runat="server"/>
Composing SQL String
The values from the three controls can be used to construct anSQL WHERE clause for selecting records that meet the criterion.For instance, when "ItemType" is selected from the FieldNamelist, and " = " is selected from the Operator list, and "Database" isentered in the FieldValue textbox, then concatenating the values
" WHERE " & FieldName.SelectedItem.Value _
Operator.SelectedItem.Value & "'" & FieldValue.Text & "'“
produces the string
WHERE ItemType = 'Database'
This string can be plugged into a SELECT statement to extractrecords based on this condition test.
Composition of the SELECT statement takes place in theSortRepeater subroutine.
Display Selected Records
Sub SortRepeater (Src As Object, Args As CommandEventArgs)
SQLString = "SELECT * FROM Products"
If FieldValue.Text <> "" Then
If Operator.SelectedItem.Value = " LIKE " _ OR _
Operator.SelectedItem.Value = " Not LIKE " Then
'-- "Contains" comparison, e.g.,
'-- WHERE field LIKE 'value'
SQLString &= " WHERE " & FieldName.SelectedItem.Value _
& _ Operator.SelectedItem.Value & "'%" & FieldValue.Text _
& "%'"
Else If FieldName.SelectedItem.Value <> "ItemPrice" AND _FieldName.SelectedItem.Value <> "ItemQuantity" Then
'-- Alphanumeric comparising, e.g.,
'-- WHERE field = 'value'
Display Selected Records
SQLString &= " WHERE " & FieldName.SelectedItem.Value & _Operator.SelectedItem.Value & "'" & FieldValue.Text & "'"
Else
'-- Numeric comparison, e.g.,
'-- WHERE field = value
SQLString &= " WHERE " & FieldName.SelectedItem.Value _
& Operator.SelectedItem.Value & FieldValue.Text
End If
End If
End If
SQLString &= " ORDER BY " & Args.CommandName
SQLString &= " " & DirectionButtons.SelectedItem.Value
DisplayRepeater
End Sub
Display Selected Records
Composing the WHERE clause depends on the user havingentered a search criterion value in the textbox. If the textbox isempty this part of the subprogram is not run and no WHEREclause is appended to the SQLString.
The format of the WHERE clause differs slightly when specifyingstring versus numeric comparisons. When the comparison valueis a string, it must be enclosed in single quotes (apostrophes);when the comparison value is a number, no quotes are used. Forexample,
WHERE ItemSupplier = 'Microsoft'
WHERE ItemPrice > 100
So, the script supplies different SQL coding for the ItemNumber,ItemType, ItemSupplier, ItemName, and ItemDescription fields(which are strings whose comparison values are enclosed inapostrophes) versus the ItemPrice and ItemQuantity fields (whichare numbers whose comparison values are not enclosed in singlequotes).
Display Selected Records
When using LIKE or  Not LIKE comparisons, all values are treated asstrings and no differentiation in coding is made. The script uses thegeneral field search  LIKE '%value%' to locate the entered valueanywhere in the field.
After the WHERE clause is composed and appended to the SQLStringvariable, the ORDER BY clause is added.
SQLString &= " ORDER BY " & Args.CommandName As before, the sortfield is given by the CommandName associated with the button clicked inthe column header. Next, either ASC or DESC is appended to theSQLString depending on which of the radio buttons is checked.
SQLString &= " " & DirectionButtons.SelectedItem.Value Finally, thecompleted SQLString is issued by calling the DisplayRepeatersubprogram. The Repeater is re-bound with records matching the searchcriterion and sorted according to the button click.
SelectRepeater.aspx
Display Records w/Paging
When displaying records from a database you need tobe cautious about the length of output produced. TheProducts table includes only 20 records and easily fitson a single Web page. But consider a database tablecontaining hundreds or thousands of records. It wouldbe impractical to display all records at one time. Theneed is to display only a few records at a time and toprovide a paging mechanism for looking through thecomplete table.
In the following example, four records at a time fromthe Products table are displayed in a Repeater.Buttons call up the next set of records for viewing.
Display Records w/Paging
Example uses buttons to display subsets of records from the Productstable. Two issue surround these buttons. First, there needs to be a wayto associate a particular button with a particular subset of records fromthe table. Second, the buttons must be created dynamically, under scriptcontrol. They cannot be hard coded on the page because it is not knownin advance how many buttons are needed nor which subset of recordseach is associated with.
As records are added to the table, more buttons are needed; as recordsare deleted, fewer buttons are needed. The number of records in thetable and, therefore, the number of buttons needed cannot be knownuntil the table is first accessed in a script.
Although button controls cannot be coded directly on the page, an areacan be set aside as a "placeholder" where a script can place the buttonswhen it creates them. The asp:PlaceHolder control is designed for justthis purpose. It reserves space on the Web page within whichdynamically created controls can be placed. It has a very simple generalformat:
<asp:PlaceHolder id="valuerunat="server"/>
Display Records w/Paging
<div class="head">Product Listing - Repeater</div>
<asp:Repeater id="RepeaterDisplay" runat="server">
<HeaderTemplate>
<table id="RepeaterTable" border="1">
<tr>
<th>No</th>
<th>Type</th>
<th>Supplier</th>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th>Qty</th>
<th>Picture</th>
</tr>
</HeaderTemplate>
Display Records w/Paging
<ItemTemplate>
<tr>
<td class="center"><%# Container.DataItem("ItemNumber") %></td>
<td><%# Container.DataItem("ItemType") %></td>
<td><%# Container.DataItem("ItemSupplier") %></td>
<td><%# Container.DataItem("ItemName") %></td>
<td> <div class="box">
<%# Container.DataItem("ItemDescription") %></div> </td>
<td class="right"><%# Container.DataItem("ItemPrice") %></td>
<td class="right"><%# Container.DataItem("ItemQuantity") %></td>
<td> <img src="Pictures/<%#Container.DataItem("ItemNumber")%> _
.jpg" style="height:50px; cursor:hand" title="Click for larger image"  _
onClick="ShowPicture('<%# Container.DataItem("ItemNumber")%>.jpg')"/> </td>
 </tr>
</ItemTemplate>
<FooterTemplate> </table> </FooterTemplate>
</asp:Repeater>
Page: <asp:PlaceHolder id="PageButtons" runat="server"/>
Display Records w/Paging
Initial Repeater DisplayThe number of records perpage to display is an arbitrary choice. In this examplefour records per page is chosen. When the pageopens the first subset of records needs to be retrievedfor display in the Repeater. This is done in thefollowing portion of the script. Variable PageSize isdeclared to hold the number of records per page.
SELECT TOP n * FROM table ... to retrieve the firstPageSize number of records from the Products tableand bind them to the Repeater. This initial retrievaltakes place only the first time the page loads.
Display Records w/Paging
<SCRIPT runat="server">
Dim DBConnection As OleDbConnection
Dim DBCommand As OleDbCommand
Dim DBReader As OleDbDataReader
Dim SQLString As String
Dim PageSize As Integer = 4
Display Records w/Paging
Sub Page_Load
If Not Page.IsPostBack Then
'-- Display the first PageSize number of records
DBConnection = New OleDbConnection( _"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "SELECT TOP " & PageSize & " * FROM Products " & _
"ORDER BY ItemNumber"
DBCommand = New OleDbCommand(SQLString, DBConnection)
DBReader = DBCommand.ExecuteReader()
RepeaterDisplay.DataSource = DBReader
RepeaterDisplay.DataBind()
DBReader.Close()
DBConnection.Close()
End If ...create paging buttons
End Sub
Display Records w/Paging
Dynamic Paging ButtonsSince paging buttons are created in script theydo not take part in the page's View State. They need to be created eachtime the page loads, within the script's Page_Load subroutine.
Each paging button needs to represent a particular subset of records.When it calls a subprogram, say DisplayRepeater, to redisplay theRepeater and bind that subset of records it must pass along to thesubprogram information about which subset to display. Here is anopportunity, then, to use the CommandName property of a button topass this information to the subprogram.
Records from the Products table are retrieved in ascending order byItemNumber. Therefore, the information needed by subprogramDisplayRepeater is the first ItemNumber in the subset and the lastItemNumber in the subset.
Assume for instance that the subset of records to be displayed beginswith ItemNumber "GR1111" and ends with ItemNumber "GR4444". Acommand button containing this information could be coded as follows:
<asp:Button runat="server" Text="label"OnCommand="DisplayRepeater" CommandName="GR1111|GR4444" />
Display Records w/Paging
That is, the button's OnCommand property calls subprogramDisplayRepeater, and its CommandName property is a stringcontaining the first and last item numbers to be retrieved. Theseitem numbers are separated by a "pipe" character (|) althoughany delimiter character could be used so long as it were not partof the values in the list. When the subprogram is called it couldparse the CommandArgument argument to determine the rangeof item numbers to extract from the Products table.
This is precisely the way the example Repeater works. ThePage_Load script builds a set of buttons, each containing thestarting and ending ItemNumbers for a subset of records. Theseitem numbers are given in the CommandName property of thebuttons.
Display Records w/Paging
Determining Subsets of RecordsThe first taskin creating the paging buttons is to retrieve thefull set of item numbers from the Productstable and to assign particular subsets ofnumbers to particular buttons.
For this purpose an ArrayList is created andloaded with item numbers from the table. It iseasier to work with a fully stocked ArrayListthan try to create buttons while iteratingthrough a recordset.
Display Records w/Paging
Sub Page_Load
If Not Page.IsPostBack Then
...display initial Repeater
End If
'-- Load array ItemNumberList() with item numbers
Dim ItemNumberList = New ArrayList()
DBConnection = New OleDbConnection( _"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "SELECT ItemNumber FROM Products _
ORDER BY ItemNumber"
Display Records w/Paging
DBCommand = New OleDbCommand(SQLString, _
DBConnection)
DBReader = DBCommand.ExecuteReader()
While DBReader.Read()
ItemNumberList.Add(DBReader("ItemNumber"))
End While
DBReader.Close()
DBConnection.Close()
ItemNumberList.TrimToSize()
...
End Sub
Display Records w/Paging
At this point ArrayList ItemNumberListcontains, in sequence, all of the itemnumbers from the Products table. Now itis a matter of indexing through theArrayList, determining the beginning andending item numbers of each subset ofrecords, and creating a button for eachsubset.
Display Records w/Paging
'-- Create Paging Buttons
Dim StartIndex As Integer
Dim EndIndex As Integer
Dim StartKey As String
Dim EndKey As String
Dim i As Integer
StartIndex = 0 For i = 1 To _
Math.Ceiling(ItemNumberList.Count / PageSize)
'-- Determine starting and ending array indexes
EndIndex = StartIndex + PageSize - 1
If EndIndex > RecordCount - 1 Then
EndIndex = RecordCount - 1
End If
Display Records w/Paging
'-- Assign starting and ending item numbers
StartKey = ItemNumberList(StartIndex)
EndKey = ItemNumberList(EndIndex)
'-- Create a button and assign to placeholder
Dim PageButton As Button
PageButton = New Button()
PageButton.Text = i
PageButton.id = "P" & i
PageButton.CommandArgument = StartKey & "|" & EndKey
PageButton.Style("width") = "20px"
PageButton.Style("background-color") = "#F0F0F0"
AddHandler PageButton.Command, AddressOf DisplayRepeater
PageButtons.Controls.Add(PageButton)
StartIndex += PageSize
Next
Display Records w/Paging
The number of paging buttons needed is given bydividing the total number of item numbers in the array(ItemNumberList.Count) by the number of records perpage (PageSize). More accurately, the Math.Ceiling()method must be applied to the formula to always"round up" to the next whole number of buttons:
Math.Ceiling(ItemNumberList.Count / PageSize)
A loop running from 1 toMath.Ceiling(ItemNumberList.Count / PageSize)produces the correct number of buttons to create.Each iteration of the loop produces one of thosebuttons.
Display Records w/Paging
Each button requires a CommandName propertycomposed of the first and last item numbers for itsparticular subset. The ArrayList index of these itemnumbers occurs in multiples of the PageSize. That is,for a Products table of 20 records retrieved 4 at a timethe ArrayList locations of the beginning and endingitem numbers for 5 buttons can be shown as: 1 (0)-(3),2 (4)-(7), 3(8)-(11), 4 (12)-(15)
The first portion of script within the loop determinesthese ArrayList indexes of the item numbers to assignto a button and extracts them from the array forassignment to variables StartKey and EndKey.
Display Records w/Paging
StartIndex = 0
For i = 1 To Math.Ceiling(ItemNumberList.Count/ PageSize)
'-- Determine starting and ending array indexes
EndIndex = StartIndex + (PageSize - 1)
If EndIndex > ItemNumberList.Count - 1 Then
 EndIndex = ItemNumberList.Count - 1
End If
Display Records w/Paging
'-- Assign starting and ending item numbers
 StartKey = ItemNumberList(StartIndex)
EndKey = ItemNumberList(EndIndex)
...
StartIndex = EndIndex + 1
Next
The StartIndex for the array (the index of the beginning itemnumber for the first button) is 0. The EndIndex (the index of theending item number for the first button) is StartIndex + (PageSize- 1). For the first button StartIndex = 0 and EndIndex = 3,spanning the four array elements containing the item numbersassociated with this first button. Using these indexes, StartKey isassigned the item number in ItemNumberList(0) and EndKey isassigned the item number in ItemNumberList(3).
Display Records w/Paging
At the end of the loop the StartIndex is moved forwardto point to the array element following the previousEndIndex element (StartIndex = EndIndex + 1). Duringthe next iteration of the loop StartIndex = 4 andEndIndex = 7, and the item numbers in array elements4 and 7 get assigned to the second button. Thisindexing continues until all five buttons are created.
Depending on the number of records in the Productstable there is a good possibility that the last buttonretrieves fewer records than the other buttons. Forexample, if the table contains only 18 records then thelast button retrieves only two records (4 + 4 + 4 + 4 +2). This is why an "end-of-array" check is made whencalculating the EndIndex for a button.
Display Records w/Paging
EndIndex = StartIndex + (PageSize - 1)
If EndIndex > ItemNumberList.Count - 1 Then
EndIndex = ItemNumberList.Count - 1
End If
If the calculation produces an index value that isbeyond the upper limit of the array, then the EndIndexis set to that last element.
In all of the calculations an index value is always oneless than a count (ItemNumberList.Count - 1 andPageSize - 1). These adjustments are neededbecause arrays are indexed beginning with 0 andcounts begin with 1.
Display Records w/Paging
Creating Buttons with ScriptsThe last section of code in the loopcreates a new asp:Button control containing a CommandNameproperty with a range of items numbers to be retrieved for display.
'-- Create a button and assign to placeholder
Dim PageButton As Button
PageButton = New Button()
PageButton.Text = i
PageButton.id = "P" & i
PageButton.CommandArgument = StartKey & "|" & EndKey
PageButton.Style("width") = "20px"
PageButton.Style("background-color") = "#F0F0F0"
AddHandler PageButton.Command, AddressOf DisplayRepeater
PageButtons.Controls.Add(PageButton)
Display Records w/Paging
A button is created programmatically by assigning it to areference variable with variable = New Button(), where variableis the programmer-supplied reference to the new button. Here,PageButton is used as this reference.
Once the button is created, its properties can be assigned. ItsText property is set to the loop index i to provide a label showingthe page number. It is given an id property by appending the loopindex to the character "P", creating buttons P1, P2, P3, P4, andP5. There is nothing significant about the id; it is simply a uniqueidentifier for the button.
The button's CommandArgument property is now set to a stringcomposed of the beginning (StartKey) and ending (EndKey) itemnumbers determined for this button, concatenated with theseparator character "|". This, finally, is what all the previous workwas about. The button is also style with a width and backgroundcolor so that all buttons have the same size and appearance.
Display Records w/Paging
To be activated, a button needs an event handler. It is supplied with an(on) Command handler to call the DisplayRepeater subroutine.
AddHandler PageButton.Command, AddressOf DisplayRepeater
An AddHandler statement is in the general format:
AddHandler object.eventAddressOf subprogram
The Visual Basic AddHandler procedure adds a named event handler toan object, specifying the AddressOf subroutine to call when the eventhandler is invoked.
With the button fully defined it is added to the placeholder created earlieras the location for paging buttons:
PageButtons.Controls.Add(PageButton)
The button is added to the placeholder's Controls collection through thecollection's Add() method as:
controlscollection.Add(object)
In this case a new PageButton object is added to thePageButtons.Controls collection. When the processing loop finishes, thefull complement of buttons will have been added to the placeholder andappear on the page.
Display Records w/Paging
Displaying the RepeaterThe paging buttonscall the DisplayRepeater subroutine to retrieveand display the subset of product recordsindicated in their CommandName property.
The subprogram needs to access thisproperty, parse the beginning and ending itemnumbers from the string, and display thoserecords.
The signature of the following subprogramrequires a call from a command button.
Display Records w/Paging
Sub DisplayRepeater (Src As Object, Args As CommandEventArgs)
Dim Keys() As String
Keys = Split(Args.CommandName, "|")
'-- Bind the Repeater
DBConnection = New OleDbConnection( _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "SELECT * FROM Products WHERE " & _
"ItemNumber >= '" & Keys(0) & "' AND " & _
"ItemNumber <= '" & Keys(1) & "' "ORDER BY ItemNumber“
DBCommand = New OleDbCommand(SQLString, DBConnection)
DBReader = DBCommand.ExecuteReader()
RepeaterDisplay.DataSource = DBReader
RepeaterDisplay.DataBind()
DBReader.Close()
DBConnection.Close()
Display Records w/Paging
'-- Highlight clicked button
Dim Item As Button
Dim ThisButton As Button
For Each Item in PageButtons.Controls
ThisButton = CType(Item, Button)
 ThisButton.Style("background-color") = "#F0F0F0“
ThisButton.Style("color") = "#000000"
Next
ThisButton = CType(PageButtons.FindControl(Src.id), _
Button)
ThisButton.Style("background-color") = "#990000“
ThisButton.Style("color") = "#FFFFFF"
End Sub
Display Records w/Paging
Extraction of the item numbers from the passedCommandArgument uses the Visual Basic Split() statement toparse the string Args.CommandArgument into elements of arrayKeys, splitting the string at the "|" character. As a result, thebeginning item number is in Keys(0) and the ending item numberis in Keys(1). Other string methods could be used, but the Split()method is automatic and easy.
Now, an appropriate SQL statement can be composed to retrievethese records:
Taking the first button as an example, the SQL statementbecomes:
SELECT * FROM Products WHERE _
ItemNumber >= 'BU1111' AND _
ItemNumber <= 'DB1111'
The statement is issued against the Products table and fourrecords are retrieved and bound to the Repeater.
Display Records w/Paging
Finding Scripted ControlsThe last statements in the subprogramhighlight the clicked button for visual emphasis, changing itsbackground and text colors. First, though, the previouslyhighlighted button needs to be un-highlighted. The script loopsthrough the placeholder's Controls collection(PageButtons.Controls) converting each control to a button object(CType(Item, Button)) and setting its background and foregroundcolors to normal.
Dim Item As Button
Dim ThisButton As Button
For Each Item in PageButtons.Controls
ThisButton = CType(Item, Button)
ThisButton.Style("background-color") = "#F0F0F0“
ThisButton.Style("color") = "#000000"
Next
Display Records w/Paging
The button that is clicked needs to be foundamong the several buttons appearing in theplaceholder so that its background andforeground colors can be set.
To locate script-generated controls on a pagethe FindControl() method of the Controlscollection is used. Its general format is shownbelow:
controlscollection.FindControl("id")
Display Records w/Paging
The identify of the button that is clicked is given by theSrc.id argument passed to the subprogram when it iscalled. Therefore, the PageButtons collection issearched to locate this control and to convert it to abutton object. Then its background and foregroundcolors can be set.
As one final touch, the first button in the group shouldbe highlighted when the page first loads and theRepeater displays the first subset of records.Therefore, a routine to do this is added at the end ofthe Page_Load script.
Display Records w/Paging
Sub Page_Load
If Not Page.IsPostBack Then
...display initial Repeater
End If
...create paging buttons
If Not Page.IsPostBack Then
Dim FirstButton As Button
FirstButton = CType(PageButtons.FindControl("P1"),Button)
FirstButton.Style("background-color") = "#990000“
FirstButton.Style("color") = "#FFFFFF"
End If
End Sub
Display Records w/Paging
The first button has id="P1" because of the naming convention chosen,so this is the control that is found and styled.
Note that is routine is not part of the previous If Not Page.IsPostBackroutine within which the Repeater is initially displayed. This first buttoncannot be highlighted until after the Page_Load script finishes creatingall the buttons. You can, though, package the Repeater display and thisroutine together as long as they both appear last in the Page_Loadscript.
As mentioned previously, the paging techniques presented here areadaptable to any of the information display controls -- asp:Repeater,asp:DataGrid, and asp:DataList. The reason these paging buttons canbe used for any of the controls is that they are not part of the controlsthemselves. They reside separately inside an asp:PlaceHolder controlthat can be displayed along side any of the information display controls.Also, when applied to other database tables, the range of keysassociated with the buttons can be easily determined from the values inthe data field used to identify subsets of records.
PagedRepeater.aspx
Adding Records
Records are added to a database tablethrough a form presenting input areas forentering the fields of information.
A button then calls a subroutine to writethe new information to the table with anSQL INSERT command.
Add Form
An add form is formatted in a table with servercontrols for data input areas. With theexception of the asp:DropDownList control forthe ItemType field, all controls areasp:TextBox controls.
Associated with these input controls areasp:Label controls for displaying errormessages resulting from data entry problems.These message areas have theirEnableViewState properties set to "False" tokeep previous messages from reappearing onform postings.
Add Form
<div class="head">Product Add</div>
<table id="AddTable" border="1" rules="rows">
<tr>
<th> Item Number: </th>
<td><asp:TextBox id="ItemNumber" runat="server" _
Columns="6“ MaxLength="6"/></td>
<td><asp:Label id="ItemNumberMessage" runat="server" _
ForeColor="#FF0000" EnableViewState="False"/></td>
</tr>
<tr>
<th> Item Type: </th>
<td><asp:DropDownList id="ItemType" runat="server"/></td>
<td></td>
</tr>
Add Form
<tr>
<th> Item Supplier: </th>
<td><asp:TextBox id="ItemSupplier" runat="server" _
Columns="40" MaxLength="50"/></td>
<td><asp:Label id="ItemSupplierMessage" runat="server" _
ForeColor="#FF0000" EnableViewState="False"/></td>
</tr> <tr>
<th> Item Name: </th>
<td><asp:TextBox id="ItemName" runat="server" _
Columns="40" MaxLength="50"/></td>
<td><asp:Label id="ItemNameMessage" runat="server" _
ForeColor="#FF0000" EnableViewState="False"/></td>
</tr>
<tr>
<th> Item Description: </th>
<td><asp:TextBox id="ItemDescription" runat="server" _
TextMode="MultiLine" Columns="45" rows="3"/></td>
<td><asp:Label id="ItemDescriptionMessage" runat="server" _
ForeColor="#FF0000" EnableViewState="False"/></td>
</tr>
Add Form
<tr>
<th> Item Price: </th>
<td>$ <asp:TextBox id="ItemPrice" runat="server" _
Columns="7" MaxLength="6"/></td>
<td><asp:Label id="ItemPriceMessage" runat="server" _
ForeColor="#FF0000" EnableViewState="False"/></td>
</tr>
<tr>
<th> Item Quantity: </th>
<td><asp:TextBox id="ItemQuantity" runat="server" _
Columns="3" MaxLength="3"/></td>
<td><asp:Label id="ItemQuantityMessage" runat="server" _
ForeColor="#FF0000" EnableViewState="False"/></td>
</tr>
</table>
Add Form
<br>
<asp:Button Text="Add Record" _
OnClick="AddRecord" runat="server"/>
<asp:Button Text="Clear Form" _
OnClick="ClearForm" runat="server"/>
<asp:Label id="AddRecordMessage" _
runat="server" ForeColor="#FF0000" _
EnableViewState="False"/>
Add Form
When defining text input areas for data to bewritten to a database, it is particularlyimportant that the length of the entered datadoes not exceed the size of the field in thedatabase. This mismatch in field sizes causesexecution errors.
Therefore, all of the asp:TextBox controlswhich have restricted sizes in the databasehave their MaxLength sizes set to the size ofthe field in the database table so that no morethan this number of characters can be entered.
Loading the Product Types
The product type input field is anasp:DropDownList supplying the validproduct types (one way of reducing thepossibility of input errors).
This list is created when the page is firstloaded by populating the control withItemType values from the Products table.
Loading the Product Types
Sub Page_Load
If Not Page.IsPostBack Then
'-- Load drop-down list with item types
DBConnection = New OleDbConnection( _
 "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "SELECT DISTINCT ItemType FROM Products _
ORDER BY ItemType"
DBCommand = New OleDbCommand(SQLString, DBConnection)
DBReader = DBCommand.ExecuteReader()
ItemType.DataSource = DBReader
ItemType.DataTextField = "ItemType"
ItemType.DataValueField = "ItemType"
ItemType.DataBind()
DBReader.Close()
DBConnection.Close()
End If
End Sub
Checking Entered Data
When the "Add Record" button is clicked, theAddRecord subroutine is called to add theentered data as a new record in the Productstable.
Before writing a record, though, the entereddata needs to be validated as best possible.
The first part of the AddRecord subroutineputs the entered data through a series ofediting checks.
Checking Entered Data
Sub AddRecord (Src As Object, Args As EventArgs)
'-- CHECK FOR VALID RECORD ---
Dim ValidRecord As Boolean = True
'-- Check for valid ItemNumber
If Len(ItemNumber.Text) <> 6 Then
ItemNumberMessage.Text = "Invalid Item Number length"
ValidRecord = False
ElseIf Not IsNumeric(Right(ItemNumber.Text,4)) Then
ItemNumberMessage.Text = "Invalid Item Number format"
ValidRecord = False
Else
ItemNumber.Text = UCase(ItemNumber.Text)
End If
Checking Entered Data
'-- Check for missing Item Supplier
If ItemSupplier.Text = "" Then
ItemSupplierMessage.Text = "Missing Item Supplier"
ValidRecord = False
End If
'-- Check for missing Item Name
If ItemName.Text = "" Then
ItemNameMessage.Text = "Missing Item Name"
ValidRecord = False
End If
 '-- Check for missing Item Description
If ItemDescription.Text = "" Then
ItemDescriptionMessage.Text = "Missing Item Description"
ValidRecord = False
End If
Checking Entered Data
'-- Check for valid Item Price
If Not IsNumeric(ItemPrice.Text) Then
ItemPriceMessage.Text = "Invalid Item Price format"
ValidRecord = False
End If
'-- Check for valid Item Quantity
If Not IsNumeric(ItemQuantity.Text) Then
ItemQuantityMessage.Text = "Invalid Item Quantity format"
ValidRecord = False
End If
If ValidRecord = True Then
...continue...
End If
End Sub
Checking Entered Data
An edit flag -- variable ValidRecord -- is initialized asTrue, and at the end of the editing routines indicateswhether or not an error was discovered in the entereddata. If its value remains True, the script can continuethe process of adding the new record to the table.
The editing routines look for missing data in a field, asufficient number of characters in the field, or, in thecase of the price and quantity fields, numericcharacters only. If an error is discovered, ValidRecordis set to False and an appropriate error message iswritten to the message label accompanying the field.
Checking for an Existing Record
If the entered data passes all the editingchecks, it is still necessary to make surethat the record being added does nothave the same ItemNumber value as anexisting record in the table.
The ItemNumber is the unique record"key," and duplicates are not allowed.
Checking for an Existing Record
If ValidRecord = True Then
'--- CHECK FOR DUPLICATE RECORD ---
DBConnection = New OleDbConnection( _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "SELECT Count(*) FROM Products " & _
WHERE ItemNumber = '" & ItemNumber.Text & "'"
DBCommand = New OleDbCommand(SQLString, DBConnection)
If DBCommand.ExecuteScalar() <> 0 Then
AddRecordMessage.Text = "Duplicate Item Number. Record _
not added."
ValidRecord = False
End If
DBConnection.Close()
End If
Checking for an Existing Record
A check for a duplicate record is madeby getting a count of the number ofrecords in the table with the sameItemNumber as was entered in the dataentry form. The following SQL statementis issued against the database:
"SELECT Count(*) FROM Products _
WHERE ItemNumber = '" & _
ItemNumber.Text & "'"
The ExecuteScalar() Method
To return a count of matching records theExecuteScalar() method of the Command object isused. This method is used when returning a singlevalue from an SQL query rather than a recordsetrequiring a data reader. In this case the singlereturned value is a count of the number of recordsmatching the input item number that can be assignedto a variable and tested:
Dim RecordCount As Integer
RecordCount = DBCommand.ExecuteScalar()
If RecordCount <> 0 Then
AddRecordMessage.Text = "Duplicate Item _
Number. Record not added."
ValidRecord = False
End If
Adding a Table Record
If all editing checks are passed and thereis not a duplicate record in the Productstable, then the new record can be addedto the table.
The database access script is placedinside a Try...Catch structure to trap forany remaining errors that could causescript execution problems.
Adding a Table Record
'-- ADD A NEW RECORD –
Try
DBConnection = New OleDbConnection( _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "INSERT INTO Products " & _
"(ItemNumber, ItemType, ItemSupplier, ItemName, " & _
"ItemDescription, ItemPrice, ItemQuantity) " & _
"VALUES (" &  "'" & ItemNumber.Text & "', " & _
"'" & ItemType.SelectedItem.Value & "', " & _
"'" & Replace(ItemSupplier.Text, "'", "''") & "', " & _
"'" & Replace(ItemName.Text, "'", "''") & "', " & _
"'" & Replace(ItemDescription.Text, "'", "''") & "', " & _
ItemPrice.Text & ", " & ItemQuantity.Text & ")"
Adding a Table Record
DBCommand = NewOleDbCommand(SQLString, DBConnection)
 DBCommand.ExecuteNonQuery
DBConnection.Close()
AddMessage.Text = "Record added“
Catch
AddMessage.Text = "Update problem. _
Record not added. " & SQLString
End Try
Adding a Table Record
The entered data values are inserted into thetable with an SQL INSERT statement. Anexample of the format of this statement whendata values are added is:
INSERT INTO Products (ItemNumber, _
ItemType, ItemSupplier, ItemName, _
ItemDescription, ItemPrice, ItemQuantity) _
VALUES ('BU5555', 'Business Office', _
'Microsoft', 'Visio', 'Description of product...', _
399.99, 10)
Adding a Table Record
The SQL statement is composed byconcatenating literal text and inputvalues, making sure to surround stringvalues with single quotes (apostrophes)and to separate values with commas.For instance, the input item number isconcatenated to the statement with:
"'" & ItemNumber.Text & "', "
Adding a Table Record
A single quote is concatenated with theinput value and with a closing singlequote to produce, say, 'BU5555' as thevalue to be written to the ItemNumberfield of the database.
Whether a string or numeric value isformatted depends on the field type inthe database.
Replacing Apostrophes in TextFields
Text fields can, themselves, containapostrophes. For instance, the ItemSupplier,ItemName, and ItemDescription fields maycontain apostrophes as part of their datavalues. When this occurs, it causes a syntaxerror in the SQL statement. For example, if thename of the supplier is Software 'R Us, thenthis value portion of the SQL statementbecomes:
'Software 'R Us'
Replacing Apostrophes in TextFields
There are too many apostrophes. It isnecessary to convert the single enclosedapostrophe to two apostrophes to handle theproblem. The Visual Basic Replace statementaccomplishes this replacement:
"'" & Replace(ItemSupplier.Text, "'", "''") & "'“
 resulting in the SQL value
'Software ''R Us'
and all is well. Any time a text field maycontain an apostrophe as part of its datavalue, make sure to replace single with doubleapostrophes.
The ExecuteNonQuery() Method
Once the SQL statement is constructed, it isissued through the Command object using theExecuteNonQuery() method. This method isused when there are no records returned bythe SQL statement and no requirement for adata reader. TheCommand.ExecuteNonQuery() method is alsoused for issuing SQL DELETE and UPDATEstatements.
After the record is added to the table, aconfirmation message is written to theAddMessage label.
Clearing the Form
Since the input form takes part in the page's ViewState, entered values are echoed back and reappearwhen the form is submitted. This makes it convenientto correct input errors in individual fields since theentire form does not have to be re-entered every timean error is made. However, once the data are writtento the database the expectation is to add anotherrecord. In this case there is inconvenience in having toedit each of the input areas to enter new data. Ameans is needed to clear the entire form.
The "Clear Form" button accomplishes this clearing ofcurrent data values to produce a blank form. Thebutton calls the ClearForm subprogram, which writesnull values to the form fields.
Clearing the Form
Sub ClearForm (Src As Object, Args As EventArgs)
ItemNumber.Text = ""
ItemSupplier.Text = ""
ItemName.Text = ""
ItemDescription.Text = ""
ItemPrice.Text = ""
ItemQuantity.Text = ""
End Sub
Of course, the ItemType DropDownList is not clearedsince these entries need to remain accessible for thenext new record.
     AddRecord.aspx
Deleting Records
Records are removed from a database tableby identifying a record and issuing an SQLcommand to delete the chosen record.
In the Products table, records are identified bytheir unique ItemNumber values. This is thefield used to choose a record for deletion.
Often, the record is retrieved and displayed forvisual verification prior to deletion.
The Delete Form
In the present example, a form presents a drop-downlist of ItemNumbers from which to choose theparticular record to delete. After that selection is made,all of the fields of that record are displayed forverification along with a "Delete Record" button.Clicking the button deletes the record from theProducts table.
The delete form is formatted in a table with servercontrols for data display areas. With the exception ofthe asp:DropDownList control for the ItemNumberfield, all controls are asp:TextBox controls withReadOnly="True" properties. This property does notpermit editing of the fields, although no harm is donein doing so.
The Delete Form
<div class="head">Product Delete</div>
<table id="DeleteTable" border="1" rules="rows" cellpadding="0">
<tr align="left">
<th> Item Number: </th>
<td><asp:DropDownList id="ItemNumbers" runat="server"/>
<asp:Button Text="Select" OnClick="SelectRecord" runat="server"/>
<asp:Label id="DeleteMessage" runat="server“ _
EnableViewState="False" ForeColor="#FF0000"/> </td>
</tr>
<asp:Panel id="DeletePanel" Visible="False" runat="server">
<tr align="left">
<th> Item Type: </th>
<td><asp:TextBox id="ItemType" runat="server" _
Columns="20" ReadOnly="True"/></td>
<td></td>
</tr>
The Delete Form
<tr align="left">
<th> Item Supplier: </th>
<td><asp:TextBox id="ItemSupplier" runat="server" _
Columns="50" ReadOnly="True"/></td>
</tr>
<tr align="left">
<th> Item Name: </th>
<td><asp:TextBox id="ItemName" runat="server" _
Columns="50" ReadOnly="True"/></td>
</tr>
<tr align="left" valign="top">
<th> Item Description: </th>
<td><asp:TextBox id="ItemDescription" runat="server" _
TextMode="MultiLine" Columns="55" rows="3"ReadOnly="True"/></td>
</tr>
The Delete Form
<tr align="left">
<th> Item Price: </th>
<td>$ <asp:TextBox id="ItemPrice" runat="server" _
Columns="7" ReadOnly="True"/></td>
</tr>
<tr align="left">
<th> Item Quantity: </th>
<td><asp:TextBox id="ItemQuantity" runat="server" _
Columns="3" ReadOnly="True"/></td>
</tr>
The Delete Form
</asp:Panel>
</table>
<br>
<asp:Button id="DeleteButton" runat="server" _
Text="Delete Record" Visible="False" _
OnClick="DeleteRecord"/>
The Delete Form
All table rows except for the first one(displaying the drop-down list of ItemNumbers)are enclosed inside an asp:Panel control withVisible="False". These display rows arehidden until an ItemNumber is selected fromthe list.
Also, the DeleteButton control below the tableis hidden until an ItemNumber is chosen. Anasp:Label control appears along side the"Select" button for display of a record deletionconfirmation message.
Creating the ItemNumber List
The asp:DropDownList of item numbers iscreated when the page is loaded. It is builtfrom the ItemNumber field in the Productstable.
Creation of the drop-down list is encapsulatedin the CreateItemNumberDropDownsubprogram rather than being coded directly inthe Page_Load routine because the list needsto be built on two separate occasions. It iscreated when the page is initially loaded, and itis recreated when a record is deleted.
Creating the ItemNumber List
When a record is deleted from the Products table thedrop-down list needs to be repopulated from scratch.The View State retains the item number of the deletedrecord in the drop-down list. However, the drop-downlist should not include this item number. So, the list isrebuilt by calling CreateItemNumberDropDown after arecord is deleted.
The list is rebuilt by first clearing its contents ofexisting items with ItemNumbers.Items.Clear(). This isa call to the Clear() method of the Items collection ofthe ItemNumbers list control. Then a new collection ofitem numbers is retrieved from the Products table andbound to the ItemNumbers DropDownList.
Creating the ItemNumber List
Sub Page_Load
If Not Page.IsPostBack Then
CreateItemNumberDropDown
End If
End Sub
Sub CreateItemNumberDropDown
ItemNumbers.Items.Clear()
DBConnection = New OleDbConnection( _"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "SELECT ItemNumber FROM Products _
ORDER BY ItemNumber"
Creating the ItemNumber List
DBCommand = NewOleDbCommand(SQLString, DBConnection)
DBReader = DBCommand.ExecuteReader()
ItemNumbers.DataSource = DBReader
ItemNumbers.DataTextField = "ItemNumber"
ItemNumbers.DataValueField = "ItemNumber"
ItemNumbers.DataBind()
DBReader.Close()
DBConnection.Close()
End Sub
Selecting a Record for Deletion
When the "Select" button is clicked, theSelectRecord subroutine is called to retrieveand display the record for visual verificationthat this is, indeed, the record to be deleted.
The selected record is retrieved by locating theone whose ItemNumber matches the onechoses from the drop-down list(ItemNumbers.SelectedItem.Value). Thissingle record is retrieved and used to populatethe text boxes in the display form. Then, thehidden panel of table rows is made visiblealong with the delete button.
Selecting a Record for Deletion
Sub SelectRecord (Src As Object, Args As EventArgs)
DBConnection = New OleDbConnection( _"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "SELECT * FROM Products " & _
"WHERE ItemNumber = '" &ItemNumbers.SelectedItem.Value & "'"
DBCommand = New OleDbCommand(SQLString,DBConnection)
DBReader = DBCommand.ExecuteReader()
DBReader.Read()
Selecting a Record for Deletion
ItemType.Text = DBReader("ItemType")
ItemSupplier.Text = DBReader("ItemSupplier")
ItemName.Text = DBReader("ItemName")
ItemDescription.Text =
DBReader("ItemDescription")
ItemPrice.Text = DBReader("ItemPrice")
ItemQuantity.Text = DBReader("ItemQuantity")
DBReader.Close()
DBConnection.Close()
DeletePanel.Visible = True
DeleteButton.Visible = True
End Sub
Deleting a Record
A click on the "Delete Record" button calls theDeleteRecord subroutine. An SQL DELETE statementis composed to delete the record whose ItemNumbermatches the one selected from the drop-down list. Thestatement is issued through the Command object'sExecuteNonQuery() method since no records arereturned from the query.
Once the record is deleted, the display fields anddelete button are made invisible again and aconfirmation message is displayed in theDeleteMessage Label control. Importantly, the drop-down list is rebuilt by calling theCreateItemNumberDropDown subroutine. Doing soensures that the just-deleted record's item number willnot reappear in the drop-down list.
Deleting a Record
Sub DeleteRecord (Src As Object, Args As EventArgs)
DBConnection = New OleDbConnection( _"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=d:\Databases\eCommerce.mdb")
DBConnection.Open()
SQLString = "DELETE FROM Products " & _
"WHERE ItemNumber = '" & ItemNumbers.SelectedItem.Value & "'"
DBCommand = New OleDbCommand(SQLString, DBConnection)
DBCommand.ExecuteNonQuery()
DBConnection.Close()
DeletePanel.Visible = False
DeleteButton.Visible = False
DeleteMessage.Text = "Record " & _
ItemNumbers.SelectedItem.Value & " deleted"
CreateItemNumberDropDown
DeleteRecord.aspx
Updating Records in a Table
Records are updated in a database table byselecting a record, changing data values in thefields, and issuing an SQL command to rewritethe changed record to the table.
Coding for the update page combines many ofthe techniques used for adding and deletingrecords.
The update form is set up much like the addform with text boxes for revising data valuesand with associated error message areasformatted as labels. As with the add form,changed values require data entry editing.
The Update Form
A form presents a drop-down list ofItemNumbers from which to choose theparticular record to update.
After the selection is made all of thefields of that record are extracted fromthe Products table and displayed alongwith an "Update Record" button.
Clicking the button rewrites the recordwith any changes made to the fields.
The Update Form
<table id="UpdateTable" border="1" rules="rows">
<tr>
<th> Item Number: </th>
<td><asp:DropDownList id="ItemNumbers" runat="server"/>
<asp:Button Text="Select" OnClick="SelectRecord" _
runat="server"/>
</td>
<td></td>
</tr>
<asp:Panel id="UpdatePanel" Visible="False" runat="server">
<tr>
<th> Item Type: </th>
<td><asp:DropDownList id="ItemType" runat="server"/></td>
<td></td>
</tr>
The Update Form
All table rows except for the drop-down list ofItemNumbers are enclosed inside anasp:Panel control with Visible="False".
These display rows are hidden until anItemNumber is selected from the list.
Also, the UpdateButton control below the tableis hidden until an ItemNumber is chosen.
An asp:Label control appears along side the"Update" button for display of a record updateconfirmation message.
Loading the Drop-Down Lists
On page load the drop-down list of itemnumbers is created.
Selecting a number from this list displays thefull form for record editing. The drop-down listof item types is also loaded. Although this listis not displayed until a record is chosen forediting it needs to be loaded only once; itsvalues are retained in View State betweenpage postings.
Selecting and Displaying a Recordfor Updating
When the "Select" button is clicked theSelectRecord subprogram is called to retrieveand display the current record. The form ismade visible for editing.
Text fields are populated from the Productstable by assigning current values from theretrieved record. Displaying the current valueof the ItemType requires that the matchingvalue be selected in the drop-down list.
Selecting and Displaying a Recordfor Updating
SQLString = "SELECT * FROM Products WHERE " & _
"ItemNumber = '" & ItemNumbers.SelectedItem.Value & "'"
Dim i As Integer
For i = 0 To ItemType.Items.Count - 1
ItemType.Items(i).Selected = False
If ItemType.Items(i).Value = DBReader("ItemType") Then
ItemType.Items(i).Selected = True
End If
Next
ItemSupplier.Text = DBReader("ItemSupplier")
...
Selecting and Displaying a Recordfor Updating
An item in a drop-down list is selected fordisplay by setting its Selected property toTrue.
At the same time the Selected property of apreviously displayed record must be set toFalse, otherwise an error results from havingtwo different items selected.
The script iterates the Items collection settingall Selected properties to False; the itemwhose value matches the value in the currentrecord has its Selected property set to True.
Updating a Record
A click on the "Update Record" button calls the UpdateRecordsubprogram. As is the case for adding a record, changed fieldsrequire editing to ensure that only valid data are rewritten to thetable.
Updating is performed with the SQL UPDATE statement issuedthrough the Command object's ExecuteNonQuery() method. Norecordset is returned from the query. With all the literals andinserted values in place the UPDATE statement resembles thefollowing example:
UPDATE Products SET ItemType='Business Office', _
ItemSupplier='Microsoft', ItemName='Office 2003 Professional', _
ItemDescription='...description...', ItemPrice=459.75, _
ItemQuantity=25 WHERE ItemNumber='BU1111'
Updating a Record
Update statements are enclosed within a Try...Catchstructure to trap any rewrite errors. When updating iscomplete a confirmation message is displayed.
The ItemNumber field is not updated. This is therecord "key" and no change in this value is permitted.
If the value were inadvertently changed then thewrong record would be updated. Changing the keyfield is akin to adding a new record to the table.
To change an item number, delete the existing recordwith this key and add an entirely new record.
UpdateRecord.aspx