dbexpress求教 |
答題得分者是:Brian77
|
xsh123
一般會員 發表:12 回覆:18 積分:6 註冊:2003-08-04 發送簡訊給我 |
用DBEXPREE时,如果数据集中一条数据已经修改,并且已经ApplyUpdates,而另一台终端也修改了同一条数据,就会报一个HandleReconcileError窗体,但是选择修改数据却没有用,数据库不更新,为什么?
程序如下:
procedure TForm1.Button1Click(Sender: TObject);
var
TD: TTransactionDesc;
begin
if not SQLConnection1.InTransaction then
begin
TD.TransactionID := 1;
TD.IsolationLevel := xilREADCOMMITTED;
SQLConnection1.StartTransaction(TD);
try
SimpleDataSet1.ApplyUpdates(0);
sqlconnection1.Commit(td);
except
SQLConnection1.Rollback(TD);
end;
end;
end; procedure TForm1.SimpleDataSet1ReconcileError(
DataSet: TCustomClientDataSet; E: EReconcileError;
UpdateKind: TUpdateKind; var Action: TReconcileAction);
begin
Action := HandleReconcileError(DataSet, UpdateKind, E);
end;
为什么另一客户端修改了没有用?
HandleReconcileError窗口报的错误信息
Record not found or changed by another user
我选择Reconcile action中的Correct但是数据不会有任何改变,仍然不会回写数据库.
有什么办法,急急急
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
|
xsh123
一般會員 發表:12 回覆:18 積分:6 註冊:2003-08-04 發送簡訊給我 |
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
一樣的意思.. TSimpleDataSet = TSQLQuery TDataSetProvider TClientDataSet
TDataSetProvider 的 UpdateMode 預設值是 WhereAll
而 TSQLQuery 中各欄位的 ProviderOptions 預設值是勾選了 pfInWhere
也就是說更寫時, DataSetProvider 會以各欄位 OldValue 去資料表裡面找記錄, 然後用 NewValue 回寫回去
但如果該記錄已被修改, 就會變成沒有記錄是與 OldValue 相符合的, 就會跑出那個訊息, 即 (無符合的資料或已被其他人修改)
方法.. 只保留 Primary Key 欄位的 ProviderOptions 的 pfInWhere 為勾選, 其它欄位不要勾選
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
|
magicang
一般會員 發表:0 回覆:3 積分:0 註冊:2002-08-31 發送簡訊給我 |
|
xsh123
一般會員 發表:12 回覆:18 積分:6 註冊:2003-08-04 發送簡訊給我 |
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
我將我的方法再詳細描述一次, 剛剛有測試過了, 這方法有是效的
我測試的 Form 內放了 TSQLConnection、TSQLQuery、TDataSetProvider、TClientDataSet、TDataSource、TDBGrid、TDBNavigator 各一個
TSQLConnection 指定 Connection Name 使它和資料庫連接
TSQLQuery 連上 TSQLConnection, 指定 SQL (為最簡單的 SELECT * FROM ...), 然後拉出所有的欄位, 除了 PK 不動, 其它的欄位的 ProviderFlags 去掉 pfInWhere
TDataSetProvider 連上 TSQLQuery
TClientDataSet 連上 TDataSetProvider, 並撰寫 AfterPost (內容就是資料庫交易和 ApplyUpdate) 及 ReconcileError (呼叫 HandleReconcileError)
TDataSource,TDBGrid,TDBNavigater 設好基本屬性.. (注意喔, PK 的 pfInWhere 要保持勾選喔, 非 PK 的則去掉) Build 出執行檔後, 執行兩份(A和B), 進行測試...
針對同一筆資料, A 先異動(PK不異動), 儲存後, B 異動(不管含不含PK), 可成功的儲存 (A,B都按一下更新鈕, 會發現資料以 B 的為最新)
針對同一筆資料, A 先異動(包含PK), 儲存後, B 異動(不管含不含PK), 出現 "Record not found or changed by another user" 訊息
按取消, 或者選修正並將PK值改成A所輸入的新PK值, 即可通過
|
xsh123
一般會員 發表:12 回覆:18 積分:6 註冊:2003-08-04 發送簡訊給我 |
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
我說的 PK 即是指 Primary Key
因為看你寫到.. 有修改了 Primary Key 欄位的 ProviderFlags
所以想到要提的是... 要去掉 pfInWhere 的, 是非 Primary Key 欄位的
Primary Key 欄位反而要保留住 pfInWhere
假設表格 T1 有欄位 F1,F2,F3, 其中 F1 包含 pfInwhere, 另兩個不包含
那麼更新檔, DataSetProvider 會使用類似 UPDATE T1 SET F1=:F1,F2=:F2,F3=:F3 WHERE F1=:OldF1 的語法
|
xsh123
一般會員 發表:12 回覆:18 積分:6 註冊:2003-08-04 發送簡訊給我 |
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
|
xsh123
一般會員 發表:12 回覆:18 積分:6 註冊:2003-08-04 發送簡訊給我 |
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
我想, 問題就出在 TSimpleDataSet, 李維先生在研討會和著作的書籍中也建議大家使用 TSQLQuery TDataSetProvider TClientDataSet 的方式
雖然 TSimpleDataSet 一樣是由這三個元件包裝而成, 但許多 Property Method Event 被隱藏了.
當修改 TSimpleDataSet 拉出來的 TField 的 ProviderFlags 時, 實際上是修改到了 TClientDataSet 這一層的 TField.ProviderFlags
而我們要修改的應該是 TSQLQuery 的 TField.ProviderFlags
因此不論你怎麼改, TSQLMonitor 所觀察到的 SQL 語句都不受影響
所以建議你棄用 TSimpleDataSet
我個人一向不使用 TSimpleDataSet (以李先生的建議是, 對於一些 Simple 的事務, 可交由它處理, 其它的事務還是以分成三元件的撰寫方式為佳)
使用 TSQLQuery TDataSetProvider TClientDataSet 還有別的好處
當要改用 ADO 時, 只要把 TSQLQuery 換成 TADOQuery 即可
當要改成三層式時, 只要把 TSQLQuery 和 TDataSetProvider 搬到中間層即可
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |