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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With