TCustomADODataSet catching EOleException (not EDatabaseError)
ado, delphi
Solution
I've tried to utilize the `System.RaiseList` to get the `TRaiseFrame.NextRaise` to no avail - I'm not getting the desired `EOleException`... So I found a rather elegant solution which is specific to my case (ADO) and does not rely on the RTL - I'm testing the `Errors` object of the `TADODataSet.Connection`:
procedure TForm1.DataSetCommit(ds: TADODataSet);
begin
ds.Connection.BeginTrans;
try
try
ds.Post;
except
on E: EDatabaseError do
begin
if Assigned(ds.Connection.Errors) and (ds.Connection.Errors.Count > 0) then
with ds.Connection.Errors.Item[0] do
// if (Number = -2147217864) then ...
ShowMessage(Format('Number:%d; Source:%s; Description:%s; NativeError:%d; SQLState:%s',
[Number, Source, Description, NativeError, SQLState]));
end;
end;
ds.Connection.CommitTrans;
except
ds.Connection.RollbackTrans;
raise;
end;
end;
This will be my solution to the specific problem, but I'm still interested in other ideas on how to trap the previous exception of `EOleException`.
Problem
In some situation (in a multi-user environment) when I `Edit` a `TADODataSet` and `Post` it, I get an Exception raised by ADO: "Row cannot be located for updating. Some values may have been changed since it was last read." If I run my program from the IDE the exception is raised as `EOleException` with Error number `-2147217864`. I want to be able to catch this exception, but when I run the program outside the IDE the exception is raised as `EDatabaseError` which does not have the `ErrorCode` I need to examine. Here is part of my code: ``` procedure TForm1.DataSetCommit(ds: TADODataSet); begin ds.Connection.BeginTrans; try try ds.Post; // <- Exception is raised here except on E: EOleException do; // EOleException is NOT fired! (E.ErrorCode = -2147217864) - see "ADODB.TCustomADODataSet.InternalPost" on E: EDatabaseError do begin // todo: Handle this situation end; end; ds.Connection.CommitTrans; except ds.Connection.RollbackTrans; raise; end; end; ``` If you look in `ADODB.TCustomADODataSet.InternalPost` you will notice that it's wrapped as so: ``` procedure TCustomADODataSet.InternalPost; begin UpdateCursorPos; try ... // <- Exception is raised here except on E: Exception do DatabaseError(E.Message); end; CheckForFlyAway; end; ``` The exception is raised inside the local procedure `UpdateData`: `Recordset.Update(EmptyParam, EmptyParam);` which triggers a `EOleException` (what I need) but the wrapper raises `EDatabaseError`! (grrrrrrr). My question is how do I get my hands on the original `EOleException` so I can query `EOleException.ErrorCode`?