Handling Cached Update Errors
Go Up to Using the BDE to cache updates Index
The Borland Database Engine (BDE) specifically checks for user update conflicts and other conditions when attempting to apply updates, and reports any errors. The dataset component's Bde.DBTables.TBDEDataSet.OnUpdateError event enables you to catch and respond to errors. You should create a handler for this event if you use cached updates. If you do not, and an error occurs, the entire update operation fails.
Here is the skeleton code for an OnUpdateError event handler:
procedure TForm1.DataSetUpdateError(DataSet: TDataSet; E: EDatabaseError; UpdateKind: TUpdateKind; var UpdateAction: TUpdateAction); begin { ... perform update error handling here ... } end;
void __fastcall TForm1::DataSetUpdateError(TDataSet *DataSet, EDatabaseError *E, TUpdateKind UpdateKind, TUpdateAction &UpdateAction) { // Respond to errors here... }
DataSet references the dataset to which updates are applied. You can use this dataset to access new and old values during error handling. The original values for fields in each record are stored in a read-only TField property called OldValue. Changed values are stored in the analogous TField property NewValue. These values provide the only way to inspect and change update values in the event handler.
The E parameter is usually of type EDBEngineError. From this exception type, you can extract an error message that you can display to users in your error handler. For example, the following code could be used to display the error message in the caption of a dialog box:
ErrorLabel.Caption := E.Message;
ErrorLabel->Caption = E->Message;
This parameter is also useful for determining the actual cause of the update error. You can extract specific error codes from EDBEngineError, and take appropriate action based on it.
The UpdateKind parameter describes the type of update that generated the error. Unless your error handler takes special actions based on the type of update being carried out, your code probably will not make use of this parameter.
The following table lists possible values for UpdateKind:
UpdateKind values
Value | Meaning |
---|---|
ukModify |
Editing an existing record caused an error. |
ukInsert |
Inserting a new record caused an error. |
ukDelete |
Deleting an existing record caused an error. |
UpdateAction
tells the BDE how to proceed with the update process when your event handler exits. When your update error handler is first called, the value for this parameter is always set to uaFail. Based on the error condition for the record that caused the error and what you do to correct it, you typically set UpdateAction
to a different value before exiting the handler:
- If your error handler can correct the error condition that caused the handler to be invoked, set
UpdateAction
to the appropriate action to take on exit. For error conditions you correct, setUpdateAction
to uaRetry to apply the update for the record again. - When set to uaSkip, the update for the row that caused the error is skipped, and the update for the record remains in the cache after all other updates are completed.
- Both uaFail and uaAbort cause the entire update operation to end. uaFail raises an exception and displays an error message. uaAbort raises a silent exception (does not display an error message).
The following code shows an OnUpdateError event handler that checks to see if the update error is related to a key violation and, if it is, it sets the UpdateAction
parameter to uaSkip:
{ Add 'Bde' to your uses clause for this example } if (E is EDBEngineError) then with EDBEngineError(E) do begin if Errors[ErrorCount - 1].ErrorCode = DBIERR_KEYVIOL then UpdateAction := uaSkip { key violation, just skip this record } else UpdateAction := uaAbort; { don't know what's wrong, abort the update } end;
// include BDE.hpp in your unit file for this example void __fastcall TForm1::DataSetUpdateError(TDataSet *DataSet, EDatabaseError *E, TUpdateKind UpdateKind, TUpdateAction &UpdateAction) { UpdateAction = uaFail // initialize to fail the update if (E->ClassNameIs("EDBEngineError")) { EDBEngineError *pDBE = (EDBEngineError *)E; if (pDBE->Errors[pDBE->ErrorCount - 1]->ErrorCode == DBIERR_KEYVIOL) UpdateAction = uaSkip; // Key violation, just skip this record } }
UpdateAction
to uaAbort to turn off the system-generated error message display.