代码之家  ›  专栏  ›  技术社区  ›  markus_ja

在TDataSetProvider.OnUpdateRor中引发时,无法识别EUPDateError异常。为什么?

  •  0
  • markus_ja  · 技术社区  · 15 年前

    当我再次投掷 EUpdateError 中的异常 TDatasetProvider.OnUpdateError 事件,它不被识别为 EUPDATE错误 catch块中出现异常。它只被认为是基地 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;
    

    异常被重新抛出,但似乎 EUPDATE错误 变成了一个平缓的基础。
    有人知道,为什么班级会迷路吗?
    我需要那种类型的才能检查 .ErrorCode 了解出了什么问题并准备好正确的用户消息。

    1 回复  |  直到 15 年前
        1
  •  1
  •   Ondrej Kelle    15 年前

    不幸的是,“旧样式”的datasnap服务器异常作为纯文本(e.message)封送到客户机,因此异常类名和实例数据在进程中丢失。见 SConnect 单位, TDataBlockInterpreter.InterpretData 方法(except块)。

    编辑:这里有一个非常简单的例子给你一个想法(根本没有测试过):

    // 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;