ClientDataSet 心得

1.   與TTable、TQuery同樣,TClientDataSet也是從TDataSet繼承下來的,它一般用於多層體系結構的客戶端。不少數據庫應用程序都用了BDE,BDE每每給發佈帶來很大的不便,於是TClientDataSet最大的特色是它不依賴於BDE(Borland Database Engine),但它須要一個動態連接庫的支持,這個動態連接庫叫DBCLIENT.DLL。在客戶端,也不須要用TDatabase構件,由於客戶端並不直接鏈接數據庫。因爲TClientDataSet是從TDataSet繼承下來的,因此,它支持諸如編輯、搜索、瀏覽、糾錯、過濾等功能。因爲 TClientDataSet在內存中創建了數據的本地副本,上述操做的執行速度很快。也正是因爲TClientDataSet並不直接鏈接數據庫,所以,客戶程序必須提供獲取數據的機制。
在Delphi 4中,TClientDataSet有三種途徑獲取數據: 
一、從文件中存取數據。 
二、從本地的另外一個數據集中獲取數據。 
三、經過IProvider接口從遠程數據庫服務器獲取數據。 
在一個客戶程序中,能夠同時運用上述三種機制獲取數據。 

和其餘數據集構件同樣,能夠用標準的數據控件顯示由TClientDataSet引入的數據集,固然,這須要藉助於TDataSource構件。因爲 TClientDataSet是從TDataSet繼承下來的,因此,凡是其餘數據集構件支持的功能,TClientDataSet構件也大體具有。不一樣的是,TClientDataSet可以在內存中創建數據的副本,所以,TClientDataSet比其餘數據集構件增長了一些特殊的功能。
在運行期,能夠調用諸如First、GotoKey、Last、Next和Prior等函數來瀏覽數據。TClientDataSet也支持書籤 (BookMark)功能,能夠用書籤來標記某條記錄,之後就能夠方便地找到這條記錄。對於TTable、TQuery等數據集構件來講,只能讀 RecNo屬性來判斷當前記錄的序號。對於TClientDataSet構件來講,還能夠寫RecNo屬性,使某一序號的記錄成爲當前記錄。

一、從文件中存取數據要從文件中讀取數據,能夠調用LoadFromFile函數。LoadFromFile函數須要傳遞一個參數,用於指定文件名。文件名應包含完整的路徑。若是客戶程序老是從一個固定的文件中讀取數據,能夠設置FileName屬性指定一個文件名,之後,當TClientDataSet 引入的數據集打開時,就自動從這個文件中讀取數據,不須要調用LoadFromFile。要從流中讀取數據,能夠調用LoadFromStream。 LoadFromStream須要傳遞一個參數,用於指定一個流對象。注意:LoadFromFile(LoadFromStream)只能從先前用 SaveToFile(SaveToStream)保存的文件中讀取數據。要把數據保存到文件中,能夠調用SaveToFile函數。 SaveToFile須要傳遞一個參數,用於指定文件名。若是指定的文件已存在,文件中的數據將被覆蓋。若是客戶程序老是把數據保存到一個固定的文件中,能夠設置FileName屬性指定一個文件名,當TClientDataSet引入的數據集關閉時,就自動把數據保存到這個文件中,不須要調用 SaveToFile。要把數據保存到流中,能夠調用SaveToStream。SaveToStream須要傳遞一個參數,指定一個流對象。注意:當把數據保存到文件或流中時,日誌中記載的修改仍然保留。這樣,當下次調用LoadFromFile或LoadFromStream讀取數據時,仍然能夠恢復原來的數據。

ClientDataSet強大的數據複製技術: 
   經過ClientDataSet.Data屬性能夠訪問客戶程序從應用服務器檢索到的數據。程序示例以下: html

[delphi]  view plain copy print ?
  1. Procedure TForm1.Button1Click(Sender: TObject);   
  2. Begin   
  3.   ClientDataSet1.Data :=   
  4.   ClientDataSet1.Provider.DataRequest(FilterEdit.Text);//在Delphi4版本之上有所改變   
  5. End;   

   也能夠直接賦值:    sql

[delphi]  view plain copy print ?

ClientDataSet1.Data:=ClientDataSet2.Data;//(至關於把ClientDataSet2的數據拷貝給ClientDataSet1,是否是很方便)  數據庫

   從其餘數據集獲取數據(除ClientDataSet):express

[delphi]  view plain copy print ?
  1. DataSetProvider1.DataSet:=DataSet;//DataSet表明一個數據集   
  2. ClientDataSet1.Data := DataSetProvider1.Data;   



3. 排序 
ClientDataSet排序 
一、簡單排序緩存

[delphi]  view plain copy print ?
  1. ClientDataSet1.IndexFieldNames:='排序字段'   

二、複雜排序(創建索引) 
下面這個過程僅供參考(由於用到三方控件DBGridEh): 服務器

[delphi]  view plain copy print ?
  1. procedure TDM1.DsSort(SortColumn: TColumnEh);   
  2. var   
  3. OldIndex:string;   
  4. begin   
  5. if (SortColumn.Grid.DataSource=nil) or (SortColumn.Grid.DataSource.DataSet=nil) or (not SortColumn.Grid.DataSource.DataSet.Active) then Exit;  
  6. OldIndex:=TClientDataSet(SortColumn.Field.DataSet).IndexName;   
  7. if OldIndex<>'' then   
  8. begin   
  9.    TClientDataSet(SortColumn.Field.DataSet).IndexName:='';   
  10.    TClientDataSet(SortColumn.Field.DataSet).DeleteIndex(OldIndex);   
  11. end;   
  12. case SortColumn.Title.SortMarker of   
  13.    smNoneEh,   
  14.    smUpEh   :TClientDataSet(SortColumn.Field.DataSet).AddIndex('px',SortColumn.Field.FieldName,[ixDescending]);  
  15.    smDownEh:TClientDataSet(SortColumn.Field.DataSet).AddIndex('px',SortColumn.Field.FieldName,[ixPrimary]);  
  16. end;   
  17. TClientDataSet(SortColumn.Field.DataSet).IndexName:='px';   
  18. end;   


把上面的過程稍作修改,可用於標準DBGridvaride

[delphi]  view plain copy print ?
  1. ASC:Boolean=True;//是否升序排列   
  2. procedure TDM1.DsSort(SortColumn: TColumn);   
  3. var   
  4. OldIndex:string;   
  5. begin   
  6. if (SortColumn.Grid.DataSource=nil) or (SortColumn.Grid.DataSource.DataSet=nil) or (not SortColumn.Grid.DataSource.DataSet.Active) then Exit;  
  7. OldIndex:=TClientDataSet(SortColumn.Field.DataSet).IndexName;   
  8. if OldIndex<>'' then   
  9. begin   
  10. TClientDataSet(SortColumn.Field.DataSet).IndexName:='';   
  11. TClientDataSet(SortColumn.Field.DataSet).DeleteIndex(OldIndex);   
  12. end;   
  13. case ASC of   
  14. Ture :TClientDataSet(SortColumn.Field.DataSet).AddIndex('px',SortColumn.Field.FieldName,[ixDescending]);//已是升序就按降序排列  
  15. else//不然按升序排列   
  16. TClientDataSet(SortColumn.Field.DataSet).AddIndex('px',SortColumn.Field.FieldName,[ixPrimary]);  
  17. end;{end case}   
  18. TClientDataSet(SortColumn.Field.DataSet).IndexName:='px';   
  19. ASC:=not ASC;   
  20. end;   


4. 提交更新過程: 
首先,客戶程序要調用ApplyUpdates函數嚮應用服務器提出申請,ApplyUpdates函數將經過IProvider接口把Delta(數據變更狀況)屬性傳遞給應用服務器。應用服務器收到客戶程序的申請後,再向遠程數據庫服務器提出申請,而且把被遠程數據庫服務器認爲出錯的記錄暫時緩存起來。應用服務器上的TDataSetProvider或TProvider構件把出錯的記錄返回給客戶程序,其中包括錯誤信息和錯誤代碼。客戶程序收到這些出錯的記錄後,能夠進行覈對和修改,而後繼續更新。注意:若是應用服務器端使用MTS類型的遠程數據模塊,就沒法提供IProvider接口,這種狀況下,必須經過遠程數據模塊的接口直接申請更新數據。
if ClientDataSet1.ChangeCount>0 then//有未決的修改 
   ClientDataSet1.ApplyUpdates(MaxErrors);//將修改提交到服務器 
參數MaxErrors用於指定一個最大錯誤數,若是出錯的記錄數超過了這個參數的值,這次更新就中止。若是MaxErrors參數設爲0,只要應用服務器發現有一個錯誤的記錄,更新操做就中止。若是MaxErrors參數設爲-1,當應用服務器發現有錯誤的記錄,就嘗試更新下一個記錄,等全部的記錄都嘗試過之後才返回。ApplyUpdates函數將返回實際遇到的錯誤數,同時,應用服務器將返回那些有錯誤的記錄。
當應用服務器收到客戶的提交請求後,觸發OnUpdateData,這時就能夠對客戶提交的數據進行檢查和編輯: 
函數

[delphi]  view plain copy print ?
Procedure TDataModule1.Provider1UpdateData(Sender:TObject;DataSet: TClientDataSet); Begin With DataSet Do Begin First; While not Eof Do Begin If UpdateStatus = usInserted then Begin Edit; FieldByName('DateCreated').AsDateTime := Date; Post; End; Next; End; End; End; 

 

  


而後將編輯後的數據提交到數據庫服務器。 
ClientDataSet1.CancelUpdates;//恢復全部修改過但未提交(包括提交未成功的)的記錄 
ClientDataSet1.UndoLastChange;//恢復前一次的修改,至關於Undo功能 
注意使用這種提交方式(ApplyUpdates)在查詢時儘量避免使用數據處理(關聯、分組、求和等等等),不然不能提交(除非本身寫一些特殊處理程序)post

 
在三層結構中,TClientDataSet的地位是不可估量的,她的使用正確與否,是十分關鍵的,本文從如下幾個方面闡述她的使用,但願對你有所幫助.
1.動態索引
[delphi]  view plain copy print ?

   

procedure TForm1.DBGrid1TitleClick(Column: TColumn); begin  
if (not column.Field is Tblobfield) then//Tblobfield不能索引,二進制 
ClientDataSet1.IndexFieldNames:=column.Field.FieldName; end;</span>

 


2.多層結構中主從表的實現
設主表ClientDataSet1.packetrecord爲-1,全部記錄
設從表ClientDataSet1.packetrecord爲0,當前記錄
3.Taggregates使用
(1)在字段編輯中add new field類型爲aggregates
後設置expression(表達試)
設置active:=true便可
使用dbedit的field爲前者便可
(2)使用Aggergates屬性add設計表達試
調用
[delphi]  view plain copy print ?
  1. <span style="font-size:13px;">  showmessage(floattostr(ClientDataSet1.Aggregates.Count));  
  2.   showmessage(ClientDataSet1.Aggregates.Items[0].Value);</span>  
 
4.在單層數據庫中不要BDE
使用ClientDataSet代替table,使用ClientDataSet的loadfilename裝入cds
代替table的tablename的db或者dbf
原來的程序改造方法:
加一個ClientDataSet,使用右鍵assign locate data
後savetofile,再loadfromfile,後刪除table
將原連table的datasource設爲ClientDataSet
惟一注意的是:要將midas.dll拷到system或者當前目錄
5.三層結構的公文包的實現方法
同時設定1:filename(*.cds)2.remote server
6.能夠對data賦值(從另外一個數據集取值)
 

ClientDataSet2.Data:=ClientDataSet1.Data;  測試

ClientDataSet2.Open;


或者

ClientDataSet2.CloneCursor(ClientDataSet1,true);  

ClientDataSet2.Open;  

 
7.附加數據取得
客戶程序嚮應用服務器請求數據。若是TClientDataSet 的
FetchOnDemand 屬性設爲True,
客戶程序會根據須要自動檢索附加的數據包如BLOB字段的值或嵌套表的內容。
不然,
客戶程序須要顯式地調用GetNextPacket 才能得到這些附加的數據包。
ClientDataSet的packetrecords設置一次取得的記錄個數

8.ClientDataSet與服務器端query鏈接方法
(1)sql內容爲空
  1. <span style="font-size:13px;">ClientDataSet1.Close;  
  2. ClientDataSet1.CommandText:=edit1.Text;//即sql內容  
  3. ClientDataSet1.Open;</span>  
 
對於沒有應用服務器設置filter 如:country like 'A%'
filtered=true可實現sql功能
(2)有參數
如服務端query的sql爲
select * from animals 
where name like :dd
則:客戶端ClientDataSet
[delphi]  view plain copy print ?
  1. <span style="font-size:13px;">var  
  2. pm:Tparam;  
  3. begin  
  4. ClientDataSet1.Close;  
  5. ClientDataSet1.ProviderName:='DataSetProvider1';  
  6. pm:=Tparam.Create(nil);  
  7. pm.Name:='dd';  
  8. pm.DataType:=ftString;  
  9. ClientDataSet1.Params.Clear;  
  10. ClientDataSet1.Params.AddParam(pm);  
  11. ClientDataSet1.Params.ParamByName('dd').AsString:=edit1.Text ;  
  12. ClientDataSet1.Open;  
  13. pm.Free;  
  14. end;  
  15. </span>  


9.數據的更新管理
(1)savepoint 保存目前爲止數據狀態,能夠恢復到這個狀態
var
pp:integer;
begin
pp:=ClientDataSet1.SavePoint;
ClientDataSet1.Edit;
ClientDataSet1.FieldByName('姓名').asstring:='古話';
ClientDataSet1.Post;
table1.Refresh;
end;
恢復點
ClientDataSet1.SavePoint:=pp;
(2)cancel,RevertRecord
取消對當前記錄的修改,只適合沒有post的,若是post,調用
RevertRecord
(3)cancelupdate
取消對數據庫全部的修改
(4)UndoLastChange(boolean),changecount
取消上一次的修改,能夠實現連續撤消
參數爲true:光標到恢復處
false:光標在當前位置不動
changecount返回修改記錄的次數,一個記錄修改屢次,返回只一次
但UndoLastChange只撤消一次

10.可寫的recno
對於Ttable和Tquery的recno是隻讀的,而TClientDataSet的recno可讀可寫
ClientDataSet1.recno:=5;是設第五個記錄爲當前記錄
11.數據保存
對於table使用post可更新數據
而ClientDataSet1的post只更新內存數據,要更新服務器數據要使用
ApplyUpdates(MaxErrors: Integer),他有一個參數,是容許發出錯誤的
次數,-1表示無數次,使用simpleobjectbroker時常設爲0,實現自動容錯和負載平衡 
 
 
ClientDataSet使用心得和技巧 

影響ClientDataSet處理速度的一個因素
TClientDataSet是Delphi開發數據庫時一個很是好的控件。有很強大的功能。
我經常用ClientDataSet作MemoryDataSet來使用。還能夠將ClientDataSet的數據保存爲XML,這樣就能夠作簡單的本地數據庫使用。還有不少功能就很少說了。在使用ClientDataSet的過程當中關於怎樣提升處理速度這個問題,我就我我的的一點點體會和你們分享一下。

一般狀況下咱們通常都是用
...ClientDataSet-->DataSource-->DBComponent
這樣的結構,處理數據的時候就直接操做ClientDataSet。可是大多DBComponet都會當即響應ClientDataSet的變化。若是 你是向ClientDataSet中插入不少數據時候,DBComponent就要響應幾回,並且響應過程根據不一樣的控件,速度,過程數量都不同。這樣就影響了程序的執行效率 。因此在對ClientDataSet處理中,我是用 ClientDataSet.DisableControls和ClientDataSet.EnableControls方法:打開和關閉DBComponent與ClientDataSet的數據顯示關係。
例如:
[delphi]  view plain copy print ?
  1. <span style="font-size:13px;">ClientDataSet..DisableControls;  
  2. ...  
  3. for I := to 10000 do  
  4. begin  
  5. ClientDataSet.Append;  
  6. ...  
  7. ClientDataSet.Post;  
  8. end;  
  9. ...  
  10. ClientDataSet.EnableControls  
  11. ...  
  12. </span>  
這樣作之後你會發現處理速度比之前沒有使用方法的時候有成倍的提升。 

ClientDataSet的數據查找。 
我所介紹的心得和技巧都是用ClientDataSet來作範例,也能夠應用於其餘的一些DataSet。廢話就很少說了。咱們仍是先看代碼,讓後再總結。
1.Scanning 掃描數據查找 
這是最簡單最直接也是最慢的一種方法,遍歷全部數據:
[delphi]  view plain copy print ?
  1. <span style="font-size:13px;">procedure TForm1.ScanBtnClick(Sender: TObject);  
  2. var  
  3.   Found: Boolean;  
  4. begin  
  5.   Found := False;  
  6.   ClientDataSet1.DisableControls;  
  7.   Start;  
  8.   try  
  9.     ClientDataSet1.First;  
  10.     while not ClientDataSet1.Eof do  
  11.     begin  
  12.       if ClientDataSet1.Fields[FieldListComboBox.ItemIndex].value = SearchText then  
  13.       begin  
  14.         Found := True;  
  15.         Break;  
  16.       end;  
  17.       ClientDataSet1.Next;  
  18.     end;  
  19.     Done;  
  20.   finally  
  21.     ClientDataSet1.EnableControls;  
  22.   end;  
  23.   if Found then  
  24.     ShowMessage(SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo))  
  25.   else  
  26.     ShowMessage(ScanForEdit.Text + ' not found');  
  27. end;</span>  

2.Finding 尋找數據 
最老,可是 最快 的查找方式。
使用FindKey/FindNearest來查找一條或多條符合條件的數據,固然待查找的 Field必須是一個IndexField 。能夠看出,這種基於Index的查找速度是很是快的。
[delphi]  view plain copy print ?
  1. <span style="font-size:13px;">procedure TForm1.FindKeyBtnClick(Sender:TObject);  
  2. begin  
  3.   Start;  
  4.   if ClientDataSet1.FindKey([SearchText]) then  
  5.   begin  
  6.     Done;  
  7.     StatusBar1.Panels[3].Text := SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo);  
  8.   end  
  9.   else  
  10.   begin  
  11.     Done;  
  12.     StatusBar1.Panels[3].Text := SearchText + ' not found';  
  13.   end;  
  14. end;  
  15.   
  16. procedure TForm1.FindNearestBtnClick(Sender: TObject);  
  17. begin  
  18.   Start;  
  19.   ClientDataSet1.FindNearest([SearchText ]);  
  20.   Done;  
  21.   StatusBar1.Panels[3].Text := 'The nearest match to ' + SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo);  
  22. end</span>  

3.Going 定位 
GotoKey/GotoNearest 與FindKey/FindNearest基本上沒有什麼區別。它也是基於Index的查找。惟一的區別就是在於你是怎麼定義你的查找了。代碼上也有區別:
[delphi]  view plain copy print ?
  1. <span style="font-size:13px;">ClientDataSet1.SetKey;  
  2. ClientDataSet1.FieldByName(IndexFieldName).value := SearchText;  
  3. ClientDataSet1.GotoKey;</span>  
 
就至關於
[delphi]  view plain copy print ?
  1. <span style="font-size:13px;">ClientDataSet1.FindKey([SearchText]);</span>  

要用好這兩種基於Index的查找,還須要瞭解ClientDataSet和Index機制。這裏就不詳細說明Index機制。一個基本的原則,要有Index,才能查找。

4.Locating 查找數據 
2,3兩種查找方式都是基於Index的,可是在實際應用中,可能會查找IndexField之外的Field。那咱們就可使用Locate。可是查找速度是沒有2,3兩種快的。好比:若是你查找一條紀錄9000/10000,Locate須要500ms,Scanning須要>2s,FindKey只要10ms(可是當你打開ClientData的時候,創建Index須要1s)。
  1. <span style="font-size:13px;">procedure TForm1.LocateBtnClick(Sender: TObject);  
  2. begin  
  3.   Start;  
  4.   if ClientDataSet1. Locate('Field1,Field2..',VarArrayOf['value1,value2..'], []) then  
  5.   begin  
  6.     Done;  
  7.     StatusBar1.Panels[3].Text := 'Match located at record ' +  
  8.     IntToStr(ClientDataSet1.RecNo);  
  9.   end  
  10.   else  
  11.   begin  
  12.     Done;  
  13.     StatusBar1.Panels[3].Text := 'No match located';  
  14.   end;  
  15. end;</span>  

小結:
ClientDataSet提供了好多種查找數據的方法。可是各自有其優缺點。
上面的例子中有Start;和Done,若是你有興趣,能夠加入計時點進行速度測試。
Scanning最簡單,可是最慢,由於比較慢,還得使用ClientDataSet.DisableControls和ClientDataSet.EnableControls方法(我在前面一片文章講過)。
Findkey/FindNearest(GotoKey/GotoNearest)代碼多,可是很是快。必須使用Index,不一樣的是Find須要的Index是必須創建好的,而Goto能夠在第一次使用時創建Index。
Locate使用最方便,不須要Index,可是速度沒有Find快

 

 

 

 

ClientDataSet使用心得和技巧 影響ClientDataSet處理速度的一個因素 TClientDataSet是Delphi開發數據庫時一個很是好的控件。有很強大的功能。 我經常用ClientDataSet作MemoryDataSet來使用。還能夠將ClientDataSet的數據保存爲XML,這樣就能夠作簡單的本地數據庫使用。還有不少功能就很少說了。在使用ClientDataSet的過程當中關於怎樣提升處理速度這個問題,我就我我的的一點點體會和你們分享一下。 一般狀況下咱們通常都是用 ...ClientDataSet-->DataSource-->DBComponent 這樣的結構,處理數據的時候就直接操做ClientDataSet。可是大多DBComponet都會當即響應ClientDataSet的變化。若是你是向ClientDataSet中插入不少數據時候,DBComponent就要響應幾回,並且響應過程根據不一樣的控件,速度,過程數量都不同。這樣就影響了程序的執行效率。因此在對ClientDataSet處理中,我是用ClientDataSet.DisableControls和ClientDataSet.EnableControls方法:打開和關閉DBComponent與ClientDataSet的數據顯示關係。 例如: ClientDataSet..DisableControls; ... for I := 0 to 10000 do
begin ClientDataSet.Append; ... ClientDataSet.Post; end; ... ClientDataSet.EnableControls ... 這樣作之後你會發現處理速度比之前沒有使用方法的時候有成倍的提升。 ClientDataSet的數據查找。 我所介紹的心得和技巧都是用ClientDataSet來作範例,也能夠應用於其餘的一些DataSet。廢話就很少說了。咱們仍是先看代碼,讓後再總結。 1.Scanning 掃描數據查找 這是最簡單最直接也是最慢的一種方法,遍歷全部數據: procedure TForm1.ScanBtnClick(Sender: TObject); var Found: Boolean; begin Found := False; ClientDataSet1.DisableControls; Start; try ClientDataSet1.First; while not ClientDataSet1.Eof do  
    begin  
      if ClientDataSet1.Fields[FieldListComboBox.ItemIndex].value = SearchText then  
      begin Found := True; Break; end; ClientDataSet1.Next; end; Done; finally ClientDataSet1.EnableControls; end; if Found then ShowMessage(SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo)) else ShowMessage(ScanForEdit.Text + ' not found'); end; procedure TForm1.ScanBtnClick(Sender: TObject); var Found: Boolean; begin Found := False; ClientDataSet1.DisableControls; Start; try ClientDataSet1.First; while not ClientDataSet1.Eof do  
    begin  
      if ClientDataSet1.Fields[FieldListComboBox.ItemIndex].value = SearchText then  
      begin Found := True; Break; end; ClientDataSet1.Next; end; Done; finally ClientDataSet1.EnableControls; end; if Found then ShowMessage(SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo)) else ShowMessage(ScanForEdit.Text + ' not found'); end; 2.Finding 尋找數據 最老,可是最快的查找方式。 使用FindKey/FindNearest來查找一條或多條符合條件的數據,固然待查找的Field必須是一個IndexField。能夠看出,這種基於Index的查找速度是很是快的。 procedure TForm1.FindKeyBtnClick(Sender: TObject); begin Start; if ClientDataSet1.FindKey([SearchText]) then  
  begin Done; StatusBar1.Panels[3].Text := SearchText +  ' found at record ' + IntToStr(ClientDataSet1.RecNo); end  
  else  
  begin Done; StatusBar1.Panels[3].Text := SearchText + ' not found'; end; end; procedure TForm1.FindNearestBtnClick(Sender: TObject); begin Start; ClientDataSet1.FindNearest([SearchText]); Done; StatusBar1.Panels[3].Text := 'The nearest match to ' +  SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo); end  
procedure TForm1.FindKeyBtnClick(Sender: TObject); begin Start; if ClientDataSet1.FindKey([SearchText]) then  
  begin Done; StatusBar1.Panels[3].Text := SearchText +  ' found at record ' + IntToStr(ClientDataSet1.RecNo); end  
  else  
  begin Done; StatusBar1.Panels[3].Text := SearchText + ' not found'; end; end; procedure TForm1.FindNearestBtnClick(Sender: TObject); begin Start; ClientDataSet1.FindNearest([SearchText]); Done; StatusBar1.Panels[3].Text := 'The nearest match to ' +  SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo); end  
  
3.Going 定位 GotoKey/GotoNearest 與FindKey/FindNearest基本上沒有什麼區別。它也是基於Index的查找。惟一的區別就是在於你是怎麼定義你的查找了。代碼上也有區別: ClientDataSet1.SetKey; ClientDataSet1.FieldByName(IndexFieldName).value := SearchText; ClientDataSet1.GotoKey; 就至關於 ClientDataSet1.FindKey([SearchText]); 要用好這兩種基於Index的查找,還須要瞭解ClientDataSet和Index機制。這裏就不詳細說明Index機制。一個基本的原則,要有Index,才能查找。 4.Locating 查找數據 2,3兩種查找方式都是基於Index的,可是在實際應用中,可能會查找IndexField之外的Field。那咱們就可使用Locate。可是查找速度是沒有2,3兩種快的。好比:若是你查找一條紀錄9000/10000,Locate須要500ms,Scanning須要>2s,FindKey只要10ms(可是當你打開ClientData的時候,創建Index須要1s)。 procedure TForm1.LocateBtnClick(Sender: TObject); begin Start; if ClientDataSet1.Locate('Field1,Field2..',VarArrayOf['value1,value2..'], []) then
  begin Done; StatusBar1.Panels[3].Text := 'Match located at record ' + IntToStr(ClientDataSet1.RecNo); end
  else
  begin Done; StatusBar1.Panels[3].Text := 'No match located'; end; end; ClientDataSet提供了好多種查找數據的方法。可是各自有其優缺點。 上面的例子中有Start;和Done,若是你有興趣,能夠加入計時點進行速度測試。 Scanning最簡單,可是最慢,由於比較慢,還得使用ClientDataSet.DisableControls和ClientDataSet.EnableControls方法(我在前面一片文章講過)。 Findkey/FindNearest(GotoKey/GotoNearest)代碼多,可是很是快。必須使用Index,不一樣的是Find須要的Index是必須創建好的,而Goto能夠在第一次使用時創建Index。 Locate使用最方便,不須要Index,可是速度沒有Find快。 var sFields : String; vResult : Variant; iCount : Integer; begin vResult := ds.Lookup('fieldnameA, fieldnameB' , VarArrayCreate([ValueA, ValueB], varVariant), 'fieldname1, fieldname2'); if (VarIsArray(vResult)) then
  begin sFields := ''; for iCount := VarArrayLowBound(vResult, 1) to VarArrayHighBound(vResult,  1) do
      begin sFields := sFields + ';' + vResult[iCount]; end; end
  else edtReturn.Text := vResult; end;
相關文章
相關標籤/搜索