2014-01-06 20 views
5

在某些情況下(在多用戶環境中),當我Edit一個TADODataSetPost它,我獲得通過ADO引發異常:TCustomADODataSet醒目EOleException(不EDatabaseError)

「行無法定位的自上次讀取以來,有些值可能已被更改爲 。「

如果我從IDE運行我的程序,異常提出爲EOleException,錯誤號爲-2147217864
我希望能夠趕上這個例外,但是當我運行該程序引發異常爲EDatabaseError IDE外部不具備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; 

如果您在ADODB.TCustomADODataSet.InternalPost看,你會發現它包裝成這樣:

procedure TCustomADODataSet.InternalPost; 
begin 
    UpdateCursorPos; 
    try 
    ... // <- Exception is raised here 
    except 
    on E: Exception do 
     DatabaseError(E.Message); 
    end; 
    CheckForFlyAway; 
end; 

唯一的例外是本地過程UpdateData裏面提出:Recordset.Update(EmptyParam, EmptyParam);這將觸發EOleException (我需要什麼),但包裝引發EDatabaseError! (grrrrrrr)。

我的問題是我如何得到我的手在原始EOleException,所以我可以查詢EOleException.ErrorCode

+1

現在你已經顯示了RTL代碼,我認爲你可以嘗試在內存中嘗試二進制修補該過程,或者劫持RTL的ExceptProc來進行地址過濾,並通過將EOLEException包裝到你自己的類中,使用形式化的消息文本json)包括你需要的所有參數。 –

+0

EOleException目的通過TCustomADODataSet.InternalPost釋放。我不認爲你已經改變了在棧上找到它。很高興你解決了它 –

+0

@ Arioch'The,你怎麼能說它被釋放? – kobik

回答

2

我試圖利用System.RaiseList得到TRaiseFrame.NextRaise無濟於事 - 我沒有得到期望的EOleException ......所以,我發現了一個相當完美的解決方案是具體我的情況下(ADO)和不依靠RTL - 我測試TADODataSet.ConnectionErrors對象:

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; 

這將是我的解決方案的具體問題,但我仍然有興趣在其他的想法如何捕獲以前例外是EOleException