2010-05-26 54 views
0

TDatasetProvider.OnUpdateError事件。當我重新拋出異常EUpdateError,它不會被識別爲在catch塊EUpdateError例外。它只被認定爲基地ExcptionEUpdateError例外。爲什麼?

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 implementaion:

procedure MyDataModule.MyDatasetProviderOnUpdateError(..;E: EUpdateError;...); 
beign 
    //Here, the expression (E is EUpdateException) returns true; 
    raise E; 
end; 

的異常重新拋出,但因爲它似乎EUpdateError被變換成一個普通基地Execption。
是否有人知道,爲什麼類類型迷路?
我需要那種類型,以檢查.ErrorCode知道什麼地方出了錯,並編寫正確的用戶信息。

回答

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; 
+0

有沒有辦法到(SQL /數據庫)錯誤代碼發送到try-except塊,爲了區分錯誤信息(爲了對錯誤代碼做出決定)? – 2010-05-29 07:06:34

+0

是的,但您必須修改和重建服務器和客戶端可執行文件。您可以包含類名並使用一些實用程序函數來傳輸特定的異常實例數據,如SQL錯誤代碼。 – 2010-05-29 12:48:38

+0

實際上,我沒有獨立的服務器客戶端應用程序。 TDataSetProvider和TClientDataSet組件位於同一個DataModule中(它是單個可執行文件)。 – 2010-05-29 12:53:40