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