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

DatasetField(NestTable) 如何加入"資料封包"?

尚未結案
VICSYS
初階會員


發表:21
回覆:64
積分:32
註冊:2002-10-10

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-08-19 13:34:42 IP:219.68.xxx.xxx 訂閱
如果是主檔或者是 MasterSource 連接的明細, 可以用下列方式,
type TACDS= class(TCustomClientDataSet);
with TACDS(cds) do
begin
AddDataPacket(
DoGetRecords(PacketRecords, RecsOut, 0, CommandText, PackageParams(Params) ),
RecsOut <> PacketRecords );
end;
這樣就可以自行控制 ClientDataSet 內的記錄!
如改變 CommandText, Params 的內容 或者是 筆數, 可以加入我想要的資料"封包"!


假設 cdsdetail 為 TClientDataSet, 該元件是用 DataSetField 讀取明細
且 cdsdetail 設定成不會自動讀取!
如果要讀取明細, 這時可以用 cdsMaster.FetchDetail 加入明細的"封包"
但是, 我想要改變加入封包的方式!

但是, 下列程式碼無法執行, 會出現 midas.dll 錯誤!
with TACDS(cdsdetail) do
begin
AddDataPacket(
DoGetRecords(PacketRecords, RecsOut, 0, CommandText, PackageParams(Params) ),
RecsOut <> PacketRecords );
end;

cdsdetail.data:= .... 也試不出來


請問 DatasetField 如何由 "資料封包" 或者 OleVariant 加入資料?

謝謝!
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-08-20 14:18:13 IP:218.163.xxx.xxx 訂閱
你好:

雖然不知你改變 FetchDetail 的行為....意圖為何

不過單純想...TCustomClientDataSet 把 AddDataPacket 放 protected 應該是有他的道理的

如果你一定要改寫...恐怕...必須完全搞清楚 TCustomClientDataSet...這個工程不小喔.
VICSYS
初階會員


發表:21
回覆:64
積分:32
註冊:2002-10-10

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-08-20 16:32:22 IP:219.68.xxx.xxx 訂閱
Delphi 在三層的架構, 提供二種  M/D 連接方式

1.MasterSource:
優點:可以控制明細的"封包", 我已經實做出明細的增量讀取!
另外也可以清空明細, 再填入合乎使用者查詢條件的封包!

缺點:在輸入期間, 主檔新增主鍵(使用者自行輸入), 明細再新增, 這時
明細的主鍵, 會保留主檔的主鍵, 在未 ApplyUpdate 前,
這時如果使用者再去改變主檔主鍵, 明細(當然)會消失!

2.DataSetField:
優點:由於主鍵會自動在 DataSetProvider(DSP) 維護, 所以沒有上述的缺點!
甚至可以做到自動序號, 新增主檔, 主鍵輸入 101*,
在 DSP 再填入 MAX(NO) 1 LIKE '101%' , 明細也可以正確異動!
(自動序號在 MasterSource 根本做不到)
缺點:
a.無法增量讀取. 只能一次讀入. 另外 poFetchDetailsOnDemand 的方式雖可以接受,
不過想想, M/D 的連接方式是在 DSP 之前, 所以當 Client 端, 移至某主檔時,
DSP 前的主檔, 也做了一虛功, 必須將 Master 的 Cursor 移至正確的位置,
DSP 才能讀取明細.
b.ClientDataSet 只能用 Filter 來查出資料, 如果使用者查出 Name like 'A*'
dbgrid 顯示出 A 開頭的資料, 這時改成 B 開頭! 明細(當然)也消失!

如果可以控制 DataSetField 的封包, 那麼可以優點合併!
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-08-21 16:20:01 IP:218.163.xxx.xxx 訂閱
Detail 如果也可以用 PacketRecord / FetchOnDemand 的機制....當然是太美麗了

不過...要實現 Detail 的 GetNextPacket Method...太難了...

尤其是來源是 DBExpress 這種 Unidirection 的 Dataset...幾乎不可能
VICSYS
初階會員


發表:21
回覆:64
積分:32
註冊:2002-10-10

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-08-21 23:21:21 IP:219.68.xxx.xxx 訂閱
MasterSource :可以控制明細的"封包", 我已經實做出明細的增量讀取!

就是利用 AddDataPacket 來實做, 當第一次加入明細封包, 傳送 CommandText 及 Params, 這時 SQLDataSet First(實際為 Reopen).
明細加入下個封包時, 不傳送 CommandText 及 Params, 這時 SQLDataSet 會讀取 DataBase 上次已讀取的下一筆 ...
這跟 Unidirection 無關, 就是要 Unidirection , 要不然 Database 的 Cursor 不知道會跑到那裡! 當然還有其他細節要處理!

所以只要能加入 DataSetField 的 "封包" ....
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-08-22 08:03:33 IP:218.163.xxx.xxx 訂閱
您似乎有點誤會我的意思...

我的意思是, 如果 Master 的 Cursor 移動過後, 回到原位置, 可否很 "漂亮的" 繼續取下一個資料包 ?

因為如果 Master 每Scroll一筆, 就必須清除 Detail, 連接 ap server, 取得 Detail 的第一個資料包, 那...付出的代價也不算小.

之所以認為 Unidirection 更難, 是因為它的 Cursor 單向性, 讓 "定位" 更繁雜.
==================
不傳送 CommandText 及 Params, 這時 SQLDataSet 會讀取 DataBase 上次已讀取的下一筆
==================
AP Server 狀態如何維持 ?
編輯記錄
Mickey 重新編輯於 2007-08-22 08:27:09, 註解 無‧
VICSYS
初階會員


發表:21
回覆:64
積分:32
註冊:2002-10-10

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-08-22 16:08:00 IP:219.68.xxx.xxx 訂閱
說的對! 如果沒有讀取完成則 Master Scroll 必須清除或保留讀取狀態.
明細資料如果讀取完成, 則加入 CacheAll 的 List.

當有大量明細資料時, 用增量模式, "付出的代價" 情況跟二層沒有不同!
當明細資料一直增量(DataBase 的 Cursor 沒有關掉 AP Server 狀態不用維持),
直到讀取完成 (Database Cursor 這時才由 DataBase 自動會 Close)
則不需要清除!

另外, 如果要 "漂亮的" 繼續取下一個資料包, 這是下一步要研究的.
採用三層架構一直在講的 "無狀態"... 狀態是保留在 Client 的 NonCacheAllList
ex.
Master Detail
1 400
2 200

Master1 "漂亮的" 繼續取下一個資料包
CommandText
SELECT * FROM SOMETABLE WHERE MasterKey=:MASTERKEY and DetailKey > 400
DetailKeyIndex= (MasterKey, DetailKey)

{
這個是"漂亮的"讀取的"定位", SQLDataSet 還是 Unidirection
如果是重讀
SELECT * FROM TABLE WHERE MasterKey=:MASTERKEY and DetailKey > -999999
SQLDataSet 還是 Unidirection
不知道版大為何要一提 Unidirection?
ClientDataSet 當然是雙向的, DSP 之前的 DataSet 應該只用 Unidirection.
}

讀取200筆之後,假設 DetailKey 最大值為 600, 更新 NoCacheAllList Master:1 Detail:600

DataBase自動自動使用 DetailKey 的 DetailKeyIndex, DataBase 端傳回 401 402... (Oracle 7 8 是這樣)
除非 Oracle 9/10, SQLServer, InterBase. 也這樣執行, 才會再研究!

增量模式當然有代價, 使用 DataBase Cursor, 必須寫控制狀態的程式或者重新讀取!
但是 DataSetField Fetch All, 的也有代價吧!
使用者讀取 10 筆, "未確認" 的盤點單, 每筆盤點單明細有上萬筆.
一次讀上萬筆 *10, 或者 poFetchDetailsOnDemand 一次讀上萬筆(DSP 前的主檔, 也做了一虛功)
還是一次讀 10 筆主檔, 200 筆明細.

視單據的情況, 我兩種方式都會用. FetchAll 或者 增量!
編輯記錄
VICSYS 重新編輯於 2007-08-22 16:14:23, 註解 無‧
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-08-22 22:09:57 IP:220.228.xxx.xxx 訂閱
感謝您精闢的說明, 顯見您曾針對此部分, 下過許多功夫...等你去把這段補起來喔....^^

1. Database 各個 Table 是否都能夠有"明確的" Key ?...例如...庫存異動紀錄...真的不容易訂出...Key

2. 為何要提 Unidirection ?...因為...認為定位時一但錯過...就必須重新 Reopen Locate...是很 "傷" 的事

3. Oracle 有 ROWNUM, ROWID 等虛擬欄位...可以用來輔助, 事實上...我用它作成"分頁"取資料, 但其他種資料庫..

4. 你的問題我並未真的深入過, 只是對以前掙扎的迷思....加以研討......就醬..........祝順利囉
VICSYS
初階會員


發表:21
回覆:64
積分:32
註冊:2002-10-10

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-08-23 00:05:07 IP:219.68.xxx.xxx 訂閱
謝謝您, 認真地考慮這個主題.

最後, 很不情願地放棄 DataSetField 加入封包!
只好, 用假的 Link Field "騙" ClientDataSet
解決了, 在輸入期間, 使用者再去改變主檔主鍵, 明細消失的問題!

主檔做一個假的唯一序號! 明細(DataSource連接), 讀取前傳送假的(主檔)序號給 DSP
這時明細的封包的 CommandText 是合乎主檔的條件,
DSP 回傳假的明細主鍵序號(剛剛傳送的序號又傳回來)
去 "騙" ClientDataSet!

好了! 用假的唯一序號, 來連接 M/D.
當新增時主檔時, 我是用負數來當主鍵,
明細的連接不是真實的 KEY Field, 所以使用去改 Key Field 也無所謂!
ApplyUpdate 前, 先異動明細的 Key Field 為主檔的 Key 值, 再去執行 ApplyUpdate!

不過自動序號的處理, 必須在 DSP 端, 所以情況比較複雜...

哈! 這一段沒有用 DataSetField 補起來, 只能用一些怪招. 不過問題解決就好! 管它完不完美.

不過我還是把這個問題留著好了, 因為如果 DataSetField 能加入封包, 可簡化不少的程式碼!
系統時間:2017-10-19 8:12:30
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!