全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2348
推到 Plurk!
推到 Facebook!

MTS之SetAbort無作用,無法取消交易之問題

缺席
l630521
資深會員


發表:15
回覆:349
積分:372
註冊:2003-02-17

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-02-03 14:49:54 IP:220.228.xxx.xxx 未訂閱
各位先進,小弟最近在嘗試寫多層架構之應用程式,在本站上參考某位大大的作法,在Server端有一個Method給Client使用,目的是要更新資料用的,程式碼如下:
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else SetComplete;
    except
      SetAbort;
      raise;
    end;
這樣子在正常狀況下沒有問題,可是小弟做了一個測試,如下面的程式碼:
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else SetAbort;
    except
      SetAbort;
      raise;
    end;
也就是做完Providers[vProvider].ApplyUpdates(vDelta, -1, EC);後,直接SetAbort,看交易是否會取消,所得到的結果是資料還是更新到資料庫了,SetAbort不是可以取消交易嗎?為什麼沒有作用呢?是哪個地方出問題了? Delphi7 ADO MTS MS SQL Server Transaction是設為Requires a transaction TDataSetProvider Options設為poAllowCommandText ResolveToDataSet True和False都設過了 SQL是由Client端之TClientDataSet.CommandText傳進來的。 請各位先進幫忙一下。謝謝! Ian
pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-02-03 17:51:15 IP:219.133.xxx.xxx 未訂閱
引言: 各位先進,小弟最近在嘗試寫多層架構之應用程式,在本站上參考某位大大的作法,在Server端有一個Method給Client使用,目的是要更新資料用的,程式碼如下:
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else SetComplete;
    except
      SetAbort;
      raise;
    end;
這樣子在正常狀況下沒有問題,可是小弟做了一個測試,如下面的程式碼:
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else SetAbort;
    except
      SetAbort;
      raise;
    end;
也就是做完Providers[vProvider].ApplyUpdates(vDelta, -1, EC);後,直接SetAbort,看交易是否會取消,所得到的結果是資料還是更新到資料庫了,SetAbort不是可以取消交易嗎?為什麼沒有作用呢?是哪個地方出問題了? Delphi7 ADO MTS MS SQL Server Transaction是設為Requires a transaction TDataSetProvider Options設為poAllowCommandText ResolveToDataSet True和False都設過了 SQL是由Client端之TClientDataSet.CommandText傳進來的。 請各位先進幫忙一下。謝謝! Ian
1. 你可以 Trace 一下,看看“else SetAbort;”是否真的RUN到了。 2. 有没有真正地进入Transsaction状态?
speedup
資深會員


發表:19
回覆:259
積分:280
註冊:2003-07-04

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-02-04 14:32:51 IP:220.135.xxx.xxx 未訂閱
引言:
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1{改成0}, EC);
      
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else SetAbort;
    except
      SetAbort;
      raise;
    end;
也就是做完Providers[vProvider].ApplyUpdates(vDelta, -1, EC);後,直接SetAbort,看交易是否會取消,所得到的結果是資料還是更新到資料庫了,
從上述的程式碼看除非EC > 0 不然是不會執行SetAbort 由於你只給片斷程式碼 很難判定 EC 是否有可能大於0 (因為看你的描述好像自行設計method 給Client 用,既然如此又何須透過CommandText傳遞SQL,直接把SQL當參數傳遞給你的Method即可) 混心雜欲 棄修身~唉 發表人 - speedup 於 2005/02/04 14:34:55
------
唉~
l630521
資深會員


發表:15
回覆:349
積分:372
註冊:2003-02-17

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-02-04 15:16:17 IP:220.228.xxx.xxx 未訂閱
引言:
引言: 各位先進,小弟最近在嘗試寫多層架構之應用程式,在本站上參考某位大大的作法,在Server端有一個Method給Client使用,目的是要更新資料用的,程式碼如下:
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else SetComplete;
    except
      SetAbort;
      raise;
    end;
這樣子在正常狀況下沒有問題,可是小弟做了一個測試,如下面的程式碼:
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else SetAbort;
    except
      SetAbort;
      raise;
    end;
也就是做完Providers[vProvider].ApplyUpdates(vDelta, -1, EC);後,直接SetAbort,看交易是否會取消,所得到的結果是資料還是更新到資料庫了,SetAbort不是可以取消交易嗎?為什麼沒有作用呢?是哪個地方出問題了? Delphi7 + ADO + MTS + MS SQL Server Transaction是設為Requires a transaction TDataSetProvider Options設為poAllowCommandText ResolveToDataSet True和False都設過了 SQL是由Client端之TClientDataSet.CommandText傳進來的。 請各位先進幫忙一下。謝謝! Ian
1. 你可以 Trace 一下,看看“else SetAbort;”是否真的RUN到了。 2. 有没有真正地进入Transsaction状态?
    
    try
      IOC := GetObjectContext;
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else IOC.SetAbort;
    except
      IOC.SetAbort;
      raise;
    end;
小弟後來參考了李維大師的大作,把程式改成上面的寫法就可以了,可是又遇到了一個問題,那就是我的程式如果停在某一筆記錄上,而其他也有程式在編修同一筆記錄的話,會產生『死結』的狀況,不知是我哪個地方沒設好!如下圖! 不好意思!小弟最近才開始學習多層式架構的程式,一切還在摸索中,麻煩各位前輩的指導! Ian
l630521
資深會員


發表:15
回覆:349
積分:372
註冊:2003-02-17

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-02-04 15:25:14 IP:220.228.xxx.xxx 未訂閱
引言:
引言:
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1{改成0}, EC);
      
      if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      else SetAbort;
    except
      SetAbort;
      raise;
    end;
也就是做完Providers[vProvider].ApplyUpdates(vDelta, -1, EC);後,直接SetAbort,看交易是否會取消,所得到的結果是資料還是更新到資料庫了,
從上述的程式碼看除非EC > 0 不然是不會執行SetAbort 由於你只給片斷程式碼 很難判定 EC 是否有可能大於0 (因為看你的描述好像自行設計method 給Client 用,既然如此又何須透過CommandText傳遞SQL,直接把SQL當參數傳遞給你的Method即可) 混心雜欲 棄修身~唉 發表人 - speedup 於 2005/02/04 14:34:55
小弟只是在測試Rollback是否正常,所以程式都是要跑SetAbort! 我程式的寫法是在Server端給一個ApplyUpdates(vProvider, vDelta: OleVariant);傳入vProvider:TDataSetProvider的Name,及vDelta:各個ClientDataSet.Delta,Client端呼叫DCOMConnection1.AppServer.ApplyUpdates('dspMaster', cdsMaster.Delta)來更新資料,想直接由Server端的TDataSetProvider透過傳過來的Delta來更新資料!原本是用ClientDataSet.ApplyUpdates(0)會更方便的,但有時可能會需要一次更新多個不同的ClientDataSet,所以才想自己來控制交易的! Ian
speedup
資深會員


發表:19
回覆:259
積分:280
註冊:2003-07-04

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-02-04 17:11:48 IP:220.135.xxx.xxx 未訂閱
引言:
引言: [quote]
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      
      //if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      // else SetAbort;
      SetAbort; //you just direct use SetAbort,if You want to testing rollback
    except
      SetAbort;
      raise;
    end;
小弟只是在測試Rollback是否正常,所以程式都是要跑SetAbort!
發表人 - speedup 於 2005/02/04 17:15:27
------
唉~
l630521
資深會員


發表:15
回覆:349
積分:372
註冊:2003-02-17

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-02-04 17:34:39 IP:220.228.xxx.xxx 未訂閱
引言:
引言:
引言: [quote]
    
    try
      if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
        Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
      
      //if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
      // else SetAbort;
      SetAbort; //you just direct use SetAbort,if You want to testing rollback
    except
      SetAbort;
      raise;
    end;
小弟只是在測試Rollback是否正常,所以程式都是要跑SetAbort!
發表人 - speedup 於 2005/02/04 17:15:27
謝謝speedup前輩,目前已可正常Rollback了,可是會有死結的問題,目前還在想辦法解決中! 過年了,先向K.Top的各位拜個早年! Ian
speedup
資深會員


發表:19
回覆:259
積分:280
註冊:2003-07-04

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-02-14 10:56:42 IP:220.135.xxx.xxx 未訂閱
引言: ...,可是會有死結的問題,目前還在想辦法解決中!
死結你是指COM 元件無法正常釋放嗎? 那應該是你的程式所提供的Method 缺少SetAbort或SetComplete (我意思說可能因例外而沒執行到) 通常有兩種作法 1.你可以在Method程式一開頭先執行SetAbort最後在加SetComplete
  SetAbort; 
  ...//Your Method code;
  SetComplete;
2.Method程式最外框加try..except
 try      ...//Your Method code;
  SetComplete;
 except
  SetAbort;
 end;    
反正切記!對於支援交易或必須交易的COM 物件方法 裡面一定要執行到SetAbort 或SetComplete 二者其一 物件才會正常釋放 混心雜欲 棄修身~唉
------
唉~
l630521
資深會員


發表:15
回覆:349
積分:372
註冊:2003-02-17

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-02-15 17:58:17 IP:220.228.xxx.xxx 未訂閱
引言:
引言: ...,可是會有死結的問題,目前還在想辦法解決中!
死結你是指COM 元件無法正常釋放嗎? 那應該是你的程式所提供的Method 缺少SetAbort或SetComplete (我意思說可能因例外而沒執行到) 通常有兩種作法 1.你可以在Method程式一開頭先執行SetAbort最後在加SetComplete
  SetAbort; 
  ...//Your Method code;
  SetComplete;
2.Method程式最外框加try..except
 try      ...//Your Method code;
  SetComplete;
 except
  SetAbort;
 end;    
反正切記!對於支援交易或必須交易的COM 物件方法 裡面一定要執行到SetAbort 或SetComplete 二者其一 物件才會正常釋放 混心雜欲 棄修身~唉
我也懷疑是大大所說的這樣,我已經把我所有的Method都加了
try
  ....My code
  SetComplete
except
  SetAbort
end;
可是還是這樣,不知和我用TSharedConnection有沒有關係,我的Server端有三個TMtsDataModule,其中MainRDM只放了一個TADOConnection,其他兩個TMtsDataModule上放了幾個TADODataSet、TDataSetProvider,都是透過MainRDM上的TADOConnection連結的。 三個TMtsDataModule我都設為需要交易,在MainRDM我用IsInTransaction測試一下,狀態都是在True,即使我下了SetComplete或SetAbort都沒用,也就是說我的MainRDM的IsInTransaction永遠是在True,不知是不是因為這樣而造成死結? Ian
speedup
資深會員


發表:19
回覆:259
積分:280
註冊:2003-07-04

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-02-16 11:09:41 IP:220.135.xxx.xxx 未訂閱
引言: 可是還是這樣,不知和我用TSharedConnection有沒有關係,我的Server端有三個TMtsDataModule,其中MainRDM只放了一個TADOConnection,其他兩個TMtsDataModule上放了幾個TADODataSet、TDataSetProvider,都是透過MainRDM上的TADOConnection連結的。 三個TMtsDataModule我都設為需要交易,在MainRDM我用IsInTransaction測試一下,狀態都是在True,即使我下了SetComplete或SetAbort都沒用,也就是說我的MainRDM的IsInTransaction永遠是在True,不知是不是因為這樣而造成死結? Ian
基本上我從未這樣寫過,原因是VCL不是Thread Safe的,COM 基本上是在Thread 模式下運作,因此任何存取共用變數(元件)都會照成無法預期的結果 (除非你有寫critical sections的相關保護程式) 你可以參考Delphi Apartment Thread Model說明 Objects can safely access their own instance data, but global data must be protected using critical sections or some other form of serialization.The thread's local variables are reliable across multiple calls. 混心雜欲 棄修身~唉
------
唉~
l630521
資深會員


發表:15
回覆:349
積分:372
註冊:2003-02-17

發送簡訊給我
#11 引用回覆 回覆 發表時間:2005-02-17 09:01:34 IP:220.228.xxx.xxx 未訂閱
引言:
引言: 可是還是這樣,不知和我用TSharedConnection有沒有關係,我的Server端有三個TMtsDataModule,其中MainRDM只放了一個TADOConnection,其他兩個TMtsDataModule上放了幾個TADODataSet、TDataSetProvider,都是透過MainRDM上的TADOConnection連結的。 三個TMtsDataModule我都設為需要交易,在MainRDM我用IsInTransaction測試一下,狀態都是在True,即使我下了SetComplete或SetAbort都沒用,也就是說我的MainRDM的IsInTransaction永遠是在True,不知是不是因為這樣而造成死結? Ian
基本上我從未這樣寫過,原因是VCL不是Thread Safe的,COM 基本上是在Thread 模式下運作,因此任何存取共用變數(元件)都會照成無法預期的結果 (除非你有寫critical sections的相關保護程式) 你可以參考Delphi Apartment Thread Model說明 Objects can safely access their own instance data, but global data must be protected using critical sections or some other form of serialization.The thread's local variables are reliable across multiple calls. 混心雜欲 棄修身~唉
謝謝speedup前輩,小弟目前還在努力研究中,至於前面所題的程式碼
  try
    IOC := GetObjectContext;
    if not VarIsEmpty(vDelta) and not VarIsNull(vDelta) then
      Providers[vProvider].ApplyUpdates(vDelta, -1, EC);
    if EC > 0 then Raise Exception.Create(UpdateErrorMsg)
    else IOC.SetAbort;
  except
    IOC.SetAbort;
    raise;
  end;
在ChildRDM中加入Activate就不用自己取得IObjectContext了! 至於TSharedConnection應該是不錯用的元件,只是好像很少找到用在MTS ADO上,所以還有待研究。 Ian
系統時間:2024-04-25 12:05:30
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!