在某些情况下(在多用户环境中),当我Edit一个TADODataSet和Post它,我获得通过ADO引发异常:
"无法找到行进行更新.某些值可能自上次读取后已更改."
如果我从IDE运行我的程序,则引发异常EOleException与错误号一样-2147217864.
我希望能够捕获此异常,但是当我在IDE外部运行程序时,会引发异常,因为我EDatabaseError没有ErrorCode需要检查.这是我的代码的一部分:
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;
Run Code Online (Sandbox Code Playgroud)
如果你看,ADODB.TCustomADODataSet.InternalPost你会注意到它被包裹如下:
procedure TCustomADODataSet.InternalPost;
begin
UpdateCursorPos;
try
... // <- Exception is raised here
except
on E: Exception do
DatabaseError(E.Message);
end;
CheckForFlyAway;
end;
Run Code Online (Sandbox Code Playgroud)
在本地过程中引发了异常UpdateData:Recordset.Update(EmptyParam, EmptyParam);触发了EOleException(我需要的)但是包装器引发了EDatabaseError!(grrrrrrr).
我的问题是我如何获得原件EOleException以便我可以查询EOleException.ErrorCode?
我试图利用 来System.RaiseList获得TRaiseFrame.NextRaise无济于事 - 我没有得到想要的EOleException......所以我找到了一个相当优雅的解决方案,它特定于我的情况(ADO)并且不依赖于 RTL - 我' m 测试Errors的对象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;
Run Code Online (Sandbox Code Playgroud)
这将是我对特定问题的解决方案,但我仍然对如何捕获先前的异常的其他想法感兴趣EOleException。