多層分散式應用程式如何處理錯誤的疑問 |
答題得分者是:Mickey
|
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
A Technical View of Borland MIDAS
(Multi-tier Distributed Application Services) http://info.borland.com/midas/papers/technical/#tdud 仔細研讀, 意思是不是 Delphi 可以做到多層分散式的功能 如文章內的圖 Figure 1: The architecture of a remote dataset. ClientDataSet1 -> DataSetProvider1 - > Table1 ClientDataSet2 -> DataSetProvider2 - > Table2 ClientDataSet3 -> DataSetProvider3 - > Table3 意思是可以對 Table1 Table2 Table3 異動! 該圖有三個 DataSetProvider(DSP), 當全部的異動是正確的情況下, 當然沒有問題! 不過當 ClientDataSet(CDS) 第一個 CDS1 成功, CDS2 失敗時, 應如何處理? 用標準元件的情況下! CDS1 執行成功後, 會執行 Reconcile, 這時 ChangeCount 會變為 0, Change Log 被清空! CDS2 假如異動時發生錯誤! 好了! 使用者把 CDS2 的錯誤修正之後, 如何再次 ApplyUpdate? CDS1 應該不會再傳送Delta 給 DSP1 異動了! 因為根本沒有 Delta (被清空了) 如果改寫 Delphi 機制, 先把 Delta 傳送給 DSP, 三個 DSP 成功後, 最後才執行 三個 CDS 的Reconcile 問題解決了? 我想問在沒有改寫元件的情況是如何處理多個 DSP 異動的處理錯誤情況! Delphi 原始元件, 只要單一個 CDS 執行成功, 就會執行 Reconcile 及 AfterApplyUpdates 這剛好是我要的! 但也不是我要的! 因為我想在 AfterApplyUpdates 處理一些程式碼, 經過Reconcile, 這時可接收到 DSP 端的 PropogateChanges 的資料! 不過當 CDS2 異動失敗後, CSD1 再也不會異動實際的資料庫... |
mustapha.wang
資深會員 發表:89 回覆:409 積分:274 註冊:2002-03-13 發送簡訊給我 |
我是这样做的:
var vResult:Variant; begin vResult:=DCOMConnection.AppServer.SaveData(VarArrayOf[ADS1.Delta,ADS2.Delta,ADS3.Delta]); CDS1.Reconcile[vResult[0]); CDS1.MergChangeLog; CDS2.Reconcile[vResult[0]); CDS2.MergChangeLog; CDS3.Reconcile[vResult[0]); CDS3.MergChangeLog; 服务器的SaveData function xxx.SaveData(ADeltas:Variant):Variant; var i:integer; begin Result:=VarArrayCreate([0,VarArrayHighBound(ADeltas,1)],varVariant); for i:=0 to VarArrayHighBound(ADeltas,1) do Result[i]:=DataSetProvider.ApplyUpdate(ADeltas[i],0);
------
江上何人初见月,江月何年初照人 |
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
|
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
|
Mickey
版主 發表:77 回覆:1882 積分:1390 註冊:2002-12-11 發送簡訊給我 |
你好:
要做到...分段 Commit... 小有名氣的資料庫...大概都有..."SAVEPOINT" 機制... 我沒實作過透過 DataSetProvider 前後端這樣...做複雜的 Transaction...都是包成 DB Stored Procedure 去做 所以...或許可以考慮 Run-time 依據 各個CDS.Delta...包裝成複雜 Transaction 的 SQL 指令... 呵呵...有點狀況外...參考參考. |
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
|
Mickey
版主 發表:77 回覆:1882 積分:1390 註冊:2002-12-11 發送簡訊給我 |
|
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
|
RootKit
資深會員 發表:16 回覆:358 積分:419 註冊:2008-01-02 發送簡訊給我 |
|
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
CDS1, CDS2, CD3 的 Reconcile, 三個 CDS 成功後, 才能一起做!
不是像範例程式! CDS1 成功後就執行 CDS1 的 Reconcile, 沒有這麼簡單! 我是把 CDS1 CDS2 CDS3 先打包為單一 Delta! 回傳時, 加入自訂的 Delta 用來控制錯誤的情況及 DSP 端的 PropogateChanges 的資料! 不知道 "Server 的 Transaction 機制拉到 Client 來做" 是否可以解決 CDS1 先執行 Reconcile 的問題! 煩請 RootKit 大大, 仔細回想您的做法. |
RootKit
資深會員 發表:16 回覆:358 積分:419 註冊:2008-01-02 發送簡訊給我 |
太久沒寫三層,五年多。
實際上 ClientDataset 對應的就是遠端的TQuery 角色(透過DataProvider)。 將 BeginTrans、RollBack、..包成Com方法。 ClientDataset 使用方法,也是使用自訂方法。 不是使用 CommandText。 當然Transation 機制就是三個成功後才寫入。 記得我那時做是很成功的。不過我現在回想不起來。 以現在功力來講當然是小巫見大巫,稍微臭屁一下! 正所謂條條大路通三層。 保重 ===================引 用 VICSYS 文 章=================== CDS1, CDS2, CD3 的 Reconcile, 三個 CDS 成功後, 才能一起做! 不是像範例程式! CDS1 成功後就執行 CDS1 的 Reconcile, 沒有這麼簡單! 我是把 CDS1 CDS2 CDS3 先打包為單一 Delta! 回傳時, 加入自訂的 Delta 用來控制錯誤的情況及 DSP 端的 PropogateChanges 的資料! 不知道 "Server 的 Transaction 機制拉到 Client 來做" 是否可以解決 CDS1 先執行 Reconcile 的問題! 煩請 RootKit 大大, 仔細回想您的做法. |
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
|
speedup
資深會員 發表:19 回覆:259 積分:280 註冊:2003-07-04 發送簡訊給我 |
如果你要異動的表格Table1 /Table2 /Table3 本身 具備Master/Detail 關係 那摸恭喜你 你可以用ClientDataSet 的Nested Table 來解決這個問題,(表身的資料可以包成表頭的一個欄位 帶回給server)
如果不是的話 那\麼你只有自行開新方法大致過程如下 把CDS1 /CDS2 /CDS3 的Delta 變成參數帶回給server 在server 在自行call Provider的applyupdate 成功後 把 三個table 的reconcile 資料包成 olevarinat 帶回 給client client 在自行做reconcile 動作
------
唉~ |
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
|
Mickey
版主 發表:77 回覆:1882 積分:1390 註冊:2002-12-11 發送簡訊給我 |
我用 SOAP Server ( DBExpres ) , 不過觀念方法 , 應該一樣吧...參考參考...
procedure StartTransaction(Connect: TSoapConnection = nil); var LConnect:TSoapConnection; begin Screen.Cursor := crHourGlass; try if Connect = nil then LConnect := g_connect else LConnect := connect; if (LConnect<>nil) then begin if not LConnect.Connected then LConnect.Open; if (LConnect.GetSOAPServer<>nil) then ISOAPApp(LConnect.GetSOAPServer).StartTransaction; end; finally Screen.Cursor := crDefault; end; end; // 使用 TClientDataset Protected Method "DoApplyUpdates" type TTempCustomClientDataSet = class(TCustomClientDataSet); procedure xxx(); var R1, R2, R3 :integer; RR1, RR2, RR3: OleVariant; begin StartTransaction; // 對應呼叫 SOAP AP Server SQLConnection.StartTransaction Method (DBExpress) try // 不能讓 ChangeLog 被 ApplyUpdates Method Merge 掉, 故使用 Protected Method if cd1.ChangeCount>0 then with TTempCustomClientDataSet(cd1) do RR1 := DoApplyUpdates(Delta, -1, R1); if cd2.ChangeCount>0 then with TTempCustomClientDataSet(cd2) do RR2 := DoApplyUpdates(Delta, -1, R2); if cd3.ChangeCount>0 then with TTempCustomClientDataSet(cd3) do RR3 := DoApplyUpdates(Delta, -1, R3); ...// do something and raise exception when error if VarIsNull(RR1) then cd1.MergeChangeLog; if VarIsNull(RR2) then cd2.MergeChangeLog; if VarIsNull(RR3) then cd3.MergeChangeLog; Commit; // 對應呼叫 SOAP AP Server SQLConnection.Commit Method (DBExpress) except cd1.CancelUpdates; cd2.CancelUpdates; cd3.CancelUpdates; Rollback; // 對應呼叫 SOAP AP Server SQLConnection.RollBack Method (DBExpress) raise; end; end; |
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
直接呼叫 DoApplyUpdates 的方式可以不用封裝 Delta!
如果 cds1 cds2 cds3 的changecount 都大於0, 當 cds3 發生 error 時! 首先, 先把 Mickey 大大程式碼, 去掉 except 內的 CancelUpdates! 因為不想清除 cds1, cds2 所做的變更! 使用者修正好 cds3 的 error, 可以再次 ApplyUpdates! 再來, 因為 cd3 發生錯誤, 所以 PR3 不為 NULL! 可以去執行 Reconcile(PR3), 得到錯誤的資訊! (使用者修正好 cds3 的 error, 再次 ApplyUpdates) 這個方式可行! 我想這個問題, 可以結案了... |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |