MS SQL + ADO 如何知道該筆 RECORD 是否別人正在 Edit |
缺席
|
cjtsif
一般會員 發表:12 回覆:13 積分:5 註冊:2002-09-18 發送簡訊給我 |
MS SQL + ADO
ADODataSet1.CursorType=clUseClient ADODataSet1.LockType=ltOptimistic 在多人作業的環境, ADODataSet1.Edit 後, 在Post之前,若該筆record有別的使用者修改並post過, ADODataSet1.Post會有Error:[找不到要更新的資料列。最後讀取的值已被變更。] 我想在ADODataSet1.BeforeEdit,查看資料庫該筆 RECORD 是否有別人正在 Edit 若有,則 abort 本以為大家都會遇到同樣問題,應該是有很多解答 但爬文許久,找不到答案 請大家幫忙,謝謝 |
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
請 Google「樂觀並行」
===================引 用 cjtsif 文 章=================== MS SQL ADO ADODataSet1.CursorType=clUseClient ADODataSet1.LockType=ltOptimistic 在多人作業的環境, ADODataSet1.Edit 後, 在Post之前,若該筆record有別的使用者修改並post過, ADODataSet1.Post會有Error:[找不到要更新的資料列。最後讀取的值已被變更。] 我想在ADODataSet1.BeforeEdit,查看資料庫該筆 RECORD 是否有別人正在 Edit 若有,則 abort 本以為大家都會遇到同樣問題,應該是有很多解答 但爬文許久,找不到答案 請大家幫忙,謝謝
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/ |
cjtsif
一般會員 發表:12 回覆:13 積分:5 註冊:2002-09-18 發送簡訊給我 |
|
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
「Start Modify之前先查看該筆 RECORD 是否有別人已進入Modify」
==> 除非你用另一個 table 記錄,否則做不到 「干脆不要 Validate,通通以user所看到維護的Commit就好」 ==> 這跟沒有並行控制一樣,有資料被互相蓋掉的危險 樂觀並行 Validate 的方法,不是在 Edit 之前,而是 Post 之前 (在 Edit 之前檢核就是悲觀並行) 會在每個資料表加入時間戳記的欄位或是記錄版本號欄位,我推薦記錄版本號欄位。 記錄版本號 INSERT 時寫 1,每次 UPDATE 都加 1 Post 之前去 select 一次,看看 table 裡的記錄版本號是否與手上的一樣,若不一樣則提醒 user,重新查詢編輯 至於為什麼不是在 Edit 之前,因為你不能預期進入 Edit 之後,電話來了講個 10 分鐘的狀況 ===================引 用 cjtsif 文 章=================== 我的做法的確是「樂觀並行」:Start Modify -> Validate -> Commit/Rollback 我想做到 1.Start Modify之前先查看該筆 RECORD 是否有別人已進入Modify 或 2.干脆不要 Validate,通通以user所看到維護的Commit就好 上面任何一種方式都好, 不知在delphi ado MSSQL,要如何做?
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/ |
cjtsif
一般會員 發表:12 回覆:13 積分:5 註冊:2002-09-18 發送簡訊給我 |
感恩sryang兄回覆,
事實上,我目前的程式,應該就是跟sryang兄提的方式一樣 在 Post 之前 ,若有ADODataSet1.onPostError, 程式檢查NativeError,若為此項error,就通知user,重新select查詢編輯 但user反應,他改了20多個欄位,不想再重打 希望他Edit之後Post之前,別人不能再Edit 另外, sryang兄提到: 1.「Start Modify之前先查看該筆 RECORD 是否有別人已進入Modify」 ==> 除非你用另一個 table 記錄,否則做不到 我有試著在Table加兩個欄位 isEditing(是否正在Edit) StartEditTM(Edit開始時間) Edit時: Step 1.if isEditing then abort Step 2.Update Table Set isEditing=True,StartEditTM=Now, Post Step 3.進入Edit,user編修 Step 4.Post前 Set isEditing=False,StartEditTM='' 雖然可行,但這樣有點麻煩,希望有比較簡單的方法 2.「干脆不要 Validate,通通以user所看到維護的Commit就好」 ==> 這跟沒有並行控制一樣,有資料被互相蓋掉的危險 Delphi ADO 要如何"不要"並行控制(資料被互相蓋掉沒關係) |
Jasonwong
版主 發表:49 回覆:931 積分:581 註冊:2006-10-27 發送簡訊給我 |
會有 "找不到要更新的資料列。最後讀取的值已被變更" 的錯誤訊息,主要原因是因為你的 ADO 的是 WHERE ALL,也就是你要 POST 資料時, SQL SERVER 會先去 WHERE 要 POST 的資料列,而 WHERE ALL 會讓 SQL SERVER 的 SELECT 語法變成
"SELECT * FROM TABLE WHERE (全部欄位)",所以你只要有一個欄位被改變你就會得到以上的錯誤訊息。 要解決此問題就要把 WHERE ALL 改成 WHERE KEY。 每個欄位屬性表裡都有一個 ProviderFlags 屬性,將 pfInUpdate 打勾,其他不要勾。只有 KEY 欄位除了將 pfInUpdate 打勾外,還要將 pfInWhere 及 pfInKey 這兩個屬性打勾。 這樣即可
------
聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心 傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心 |
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
|
cjtsif
一般會員 發表:12 回覆:13 積分:5 註冊:2002-09-18 發送簡訊給我 |
殘念です,WHERE ALL / WHERE KEY 和我的問題好像沒有關係
無論任何一個 ADODataSet1.Edit 後, 在Post之前,若該筆record有別的使用者修改並post過, ADODataSet1.Post會有Error:[找不到要更新的資料列。最後讀取的值已被變更。] 找不到要更新的資料列。最後讀取的值已被變更" 的錯誤訊息,主要原因是因為你的 ADO 的是 WHERE ALL,
編輯記錄
cjtsif 重新編輯於 2018-08-20 20:50:32, 註解 無‧
|
kurumba
一般會員 發表:0 回覆:1 積分:0 註冊:2018-09-13 發送簡訊給我 |
procedure TProcessForm.ADODataSet1AfterOpen(DataSet: TDataSet);
begin ADODataSet1.Properties.Get_Item('Update Criteria').Value := 0; end; ===================引 用 cjtsif 文 章=================== MS SQL ADO ADODataSet1.CursorType=clUseClient ADODataSet1.LockType=ltOptimistic 在多人作業的環境, ADODataSet1.Edit 後, 在Post之前,若該筆record有別的使用者修改並post過, ADODataSet1.Post會有Error:[找不到要更新的資料列。最後讀取的值已被變更。] ............... |
it1506
初階會員 發表:33 回覆:89 積分:49 註冊:2011-02-16 發送簡訊給我 |
在 SQL Server 中,支援了 11 種不同物件的鎖定機制,資料庫引擎會自己判斷資源的存取狀況決定要使用何種鎖定機制。
而資料庫引擎在決定使用何種鎖定策略前,會先決定鎖定的控制類型,先由用戶端程式所要求的控制類型來處理,若用戶端程式沒有要求時才會由資料庫的預設值來處理,而鎖定的控制類型有兩種:
編輯記錄
it1506 重新編輯於 2018-09-28 10:28:20, 註解 無‧
|
wsx1688
一般會員 發表:0 回覆:0 積分:0 註冊:2024-04-08 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |