1.6 Take Care of Error Handling with Bound Controls
When dealing with database tasks, you are going to get runtime errors. In .NET, we call
the various types of errors you can get exceptions. This How-To shows examples of what
exceptions could occur and how to handle them using the Try, Catch, and Finally
statements.
Adding and deleting records is fine, but what happens if an error occurs? You tried to
delete an existing company, and got the screen that appears in Figure 1.10.
Figure 1.10. This is an unhandled error, called an exception in .NET.
How do you make it so errors are handled gracefully within the application using bound
controls?
Technique
Error handling is one of the most important aspects of working with data, between when
a user is entering data and updating the server. If you don't have proper error handling,
your system will, in the best situation, give an ugly error message, and in the worst, blow
up and put bad data in your system. In Visual Studio .NET, errors are classes called
exceptions. Many different (inherited) types of exceptions exist.
Run-time exceptions can occur in just about any part of your application. They can be
handled by using Try...Catch...Finally or they can be unhandled, where you will see the
error in Figure 1.11.
Figure 1.11. This error was thrown up from one subroutine to the one that called it.
Take a look at a common way to trap exceptions shown in Listing 1.15.
Listing 1.15 Standard Code for Handling Exceptions
Private Sub MySub()
Try
'-Code to be handled here
Catch dataException as Exception
MessageBox.Show(dataException.Message)
Finally
'-Code that will occur regardless of if an error occurs.
End Try
End Sub
Following are some basic points to help you when working with exceptions and
Try...Catch...Finally blocks:
•
The name of the exception object can be whatever you want it to be.
dataException was just used as an example.
•
Specific types of exceptions inherit from the base class of System.Exception.
OleDbException is one of those classes, and you will see an example of using this
class in the following steps.
•
You can use the Throw statement within a Catch statement to throw the exception
back up to a calling subroutine.
•
You can use the When clause on the Catch statement to trap for specific
exceptions.
•
When multiple Catch statements are used, each one is executed unless an End Try
or End Sub is placed within a Catch block, as in this How-To.
•
You can use multiple Catch statements to handle various possible exceptions that
can occur.
You will see an example of these bullets in the following steps.
Steps
Taking the form with which you have been working, you are going to modify it to trap
exceptions when the record is being saved (either for additions or editing) and when the
record is deleted. You will also add some code in the event when closing the form.
1. Modify the code in the Click event of the command button called btnSave. You
will surround the SaveRecord routine call with a Try...Catch...End Try block. If an
exception occurs, the Show method of the MessageBox class is called, passing the
Message property of the Exception object called saveException. Next, the
subroutine is exited. If no errors occur, then life goes on, and so does the
subroutine.
Listing 1.16 frmHowTo1_6.vb: Code Added to btnSave Click Event to Trap
Save Exceptions
Private Sub btnSave_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnSave.Click
Try
'- Save the information
SaveRecord()
Catch saveException As Exception
MessageBox.Show("The following error has occurred: " & _
saveException.Message, "Error Saving Record")
Exit Sub
End Try
'- Disable the text boxes
ActivateEditing(False)
If mbAddNew Then
LoadList()
RefreshIndividual()
mbAddNew = False
End If
End Sub
2. Modify the SaveRecord routine to "throw" the exception up to the btnSave_Click
subroutine, or whatever happens to have called the SaveRecord routine. Following
is the SaveRecord subroutine with the new Try...Catch...End Try block added,
along with the Throw statement.
Listing 1.17 frmHowTo1_6.vb: Pass the Exception Back Up to the Calling
Routine
Private Sub SaveRecord()
Try
'- Use the BindingContext class to end the current editing so
' that we can update the server.
Me.BindingContext(Me.dsCustomerIndividual, _
"Customers").EndCurrentEdit()
'- Perform the requested task at the dataset
' level using the data adapter
odaCustomerIndividual.Update(dsCustomerIndividual, "Customers")
'- By accepting the changes, the data gets sent back to the server
dsCustomerIndividual.AcceptChanges()
Catch saveException As Exception
Throw saveException
End Try
End Sub
3. Now it's time to deal with adding exception handling to the btnDelete Click event,
as seen next. The Try statement is used to wrap the code that performs deletion of
the data. The code then uses a Catch statement to check whether the exception that
occurs is a specific OleDbException, 3621, which is an error having to do with
trying to delete a record when related records exist in another table. Note that you
could-and in fact should-assign this to a constant value. Because delException has
been caught as an OleDbException, you can look at the NativeError property of
the first error in the Errors collection to get the actual OleDb error number. If the
error is not 3621, then the exception is trapped with the next Catch statement, and
a messagebox is displayed. If errors occur, then the subroutine is exited before the
final lines of code are executed.
Listing 1.18 frmHowTo1_6.vb: Catching Exceptions When You're Deleting a
Record
Private Sub btnDelete_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btnDelete.Click
Try
'- Mark the row for deletion using the RemoveAt
' method of the BindingContext
Me.BindingContext(Me.dsCustomerIndividual,
"Customers").RemoveAt(Me.BindingContext(Me.dsCustomerIndividual,
"Customers").Position)
'- Perform the requested task at the dataset
' level using the data adapter
odaCustomerIndividual.Update(dsCustomerIndividual, "Customers")
'- By accepting the changes, the data gets sent back to the server
dsCustomerIndividual.AcceptChanges()
Catch delException As System.Data.OleDb.OleDbException _
When delException.Errors(0).NativeError = 3621
MessageBox.Show("An error occurred because of related order records.",
"Error Deleting Customer", _
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
Catch delException As Exception
MessageBox.Show(delException.Message, "Error Deleting Customer",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
End Try