当我在EUpdateError
事件中重新抛出TDatasetProvider.OnUpdateError
异常时,它在catch块中不会被识别为EUpdateError
异常。它仅被识别为基础Excption
。
try
...
//calls the TDatasetPorvider.OnUpdateError event.
myClientDataSet.ApplyUpdates(0);
...
except
on ex: EUpdateError do
begin
//never goes here
//Evaluate ex.ErrorCode
end;
on ex: Exception do
begin
//always goes here
//the expression (ex is EUpdateError) returns false;
end;
end;
Hiere是相应的.OnUpdateError
实现:
procedure MyDataModule.MyDatasetProviderOnUpdateError(..;E: EUpdateError;...);
beign
//Here, the expression (E is EUpdateException) returns true;
raise E;
end;
异常被重新抛出,但似乎EUpdateError
被转换为普通的基本Execption。
有谁知道,为什么班级类型迷路了?
我需要这种类型才能检查.ErrorCode
以了解出了什么问题并准备好正确的用户信息。
答案 0 :(得分:1)
不幸的是,“旧式”DataSnap服务器异常作为文本(E.Message)被编组到客户端,因此异常类名称和实例数据在此过程中丢失。请参阅SConnect
单位,TDataBlockInterpreter.InterpretData
方法(除了块)。
编辑:这是一个非常简单的例子,可以给你一个想法(根本不测试):
// new methods
function TDataBlockInterpreter.ReadException(const Data: IDataBlock): Exception;
var
Flags: TVarFlags;
AClassName, AMessage, AContext: string;
ErrorCode, PreviousError: Integer;
OriginalException: Exception;
begin
AClassName := ReadVariant(Flags, Data);
AMessage := ReadVariant(Flags, Data);
if AClassName = 'EUpdateError' then
begin
AContext := ReadVariant(Flags, Data);
ErrorCode := ReadVariant(Flags, Data);
PreviousError := ReadVariant(Flags, Data);
OriginalException := ReadException(Data);
Result := EUpdateError.Create(AMessage, AContext, ErrorCode, PreviousError, OriginalException);
end
// else if AClassName = ... then ...
else
Result := Exception.Create(AMessage);
end;
procedure TDataBlockInterpreter.WriteException(E: Exception; const Data: IDataBlock);
begin
WriteVariant(E.ClassName, Data);
WriteVariant(E.Message, Data);
if E is EUpdateError then
begin
WriteVariant(EUpdateError(E).Context, Data);
WriteVariant(EUpdateError(E).ErrorCode, Data);
WriteVariant(EUpdateError(E).PreviousError, Data);
WriteException(EUpdateError(E).OriginalException, Data);
end;
end;
// modified methods
procedure TDataBlockInterpreter.DoException(const Data: IDataBlock);
begin
raise ReadException(Data);
end;
procedure TDataBlockInterpreter.InterpretData(const Data: IDataBlock);
var
Action: Integer;
begin
Action := Data.Signature;
if (Action and asMask) = asError then DoException(Data);
try
case (Action and asMask) of
asInvoke: DoInvoke(Data);
asGetID: DoGetIDsOfNames(Data);
asCreateObject: DoCreateObject(Data);
asFreeObject: DoFreeObject(Data);
asGetServers: DoGetServerList(Data);
asGetAppServers: DoGetAppServerList(Data);
else
if not DoCustomAction(Action and asMask, Data) then
raise EInterpreterError.CreateResFmt(@SInvalidAction, [Action and asMask]);
end;
except
on E: Exception do
begin
Data.Clear;
Data.Signature := ResultSig or asError;
WriteException(E, Data);
FSendDataBlock.Send(Data, False);
end;
end;
end;