原文:https://blog.csdn.net/yangjian900109/article/details/50342439?locationNum=1&fps=1html
TClientDataSet控件繼承自TDataSet,其數據存儲文件格式擴展名爲 .cds,是基於文件型數據存儲和操做的控件。該控件封裝了對數據進行操做處理的接口和功能,而自己並不依賴上述幾種數據庫驅動程序,基本上能知足單機"瘦"數據庫應用程序的須要。sql
1.TClientDataSet的基本屬性和方法介紹數據庫
1).FieldDefs: 字段定義列表屬性express
開發者可經過單擊屬性編輯器中該屬性編輯按鈕,或在該控件上單擊右鍵選擇彈出菜單中的"Fields Editor"菜單進行字段編輯。設置完此屬性後,實際上就至關於定義了表的結構;若是想裝入已有的數據表的結構和數據,可經過單擊右鍵選擇彈出菜單中的"Assign Local Data"菜單,從彈出對話框中選取當前窗體中已與數據庫鏈接好的數據集控件名稱便可(當前窗體中必須已放置好要套用的數據集控件並打開激活)。windows
使用注意:服務器
對於自定義的字段名錶,該屬性編輯完後,該控件仍然沒法打開。必須右鍵單擊該控件,選擇彈出菜單中的"Create DataSet"菜單,讓該控件以上述編輯的字段列表爲依據,建立數據集後,纔可以被激活打開和使用。不然,會出現相似"ClientDataSet1: Missing data provider or data packet."的錯誤(包括在運行期,運行期可調用該控件的CreateDataSet方法,從而動態定義字段和表)。
2).FileName屬性編輯器
說明:數據存儲文件的名稱。ide
因該控件是基於文件型的數據操做控件,所以,必須指定所操做的數據文件名稱(默認擴展名稱.cds),從而打開和激活該控件,進而進行數據編輯。post
例1:利用此屬性打開指定的.cds文件測試
var
Path: string;
begin
Path := ExtractFilePath(Application.ExeName); //取得可執行文件路徑
CDataSet1.FileName := Path + 'test.cds';
CDataSet1.Open;
end;
3).CreateDataSet方法
說明:該方法以FieldDefs中的字段名錶爲結構創建數據集,經常使用來進行動態定義表。
例2:動態建立一具備姓名和年齡兩個字段的數據集。
//建立字段名錶
CDataSet.FieldDefs.Clear;
with CDataSet.FieldDefs.AddFieldDef do
begin
Name := 'Name';
Size := 10;
DataType := ftString;
end;
with CDataSet.FieldDefs.AddFieldDef do
begin
Name := 'Age';
DataType := ftInteger;
end;
//動態建立數據集
CDataSet.CreateDataSet;
//激活和打開該數據集
CDataSet.Open;
4).Open方法
說明: 打開和激活數據集控件,從而進行數據編輯。
a. 若是指定了FileName屬性,則直接用Open方法便可打開和激活該控件,見例1。
b. 若是未指定FileName屬性,可以使用例2方法動態建立和打開數據集,進而操做數據。
5).LoadFromFile和SaveToFile
說明:從文件中裝入表結構和數據以及存儲數據到文件。該方法相似於Word中的打開新文件和另存爲的功能。
例3:將數據集的數據存儲到指定文件中
CDataSet.SaveToFile('c:\windows\desktop\test.cds');
6).First(到首),Prior(向前),Next(向後),Last(到尾),Edit(編輯),CanCel(取消編輯),Post(保存),Insert(插入記錄),Append(添加記錄),Delete(刪除),Refresh(數據刷新)等數據集經常使用方法
說明:當指定了FileName屬性時,其Post方法可將數據存入指定的文件中,相似其SaveToFile方法;若是未指定存儲文件名,則Post方法只將數據存儲在RAM中。其它方法,同通常數據集控件使用方法,略。
7).Filter, Filtered: 過濾篩選屬性
說明:用於篩選指定條件的記錄,用法同通常數據集控件,略。
例4:在已經激活打開的數據集中篩選性別爲男性的記錄
CDataSet.Close;
CDataSet.Filter := '性別=''' + '男' + '''';
CDataSet.Filtered := True;
CDataSet.Open;
2.使用TClientDataSet控件的應用程序發佈的注意事項:
如前所述,使用TClientDataSet控件的程序發佈時不須要任何數據庫驅動程序,大大節省了安裝文件的大小。可是,在發佈程序時別忘了將Windows系統目錄下midas.dll(257KB)與應用程序一塊兒發佈(運行必須),不然,程序仍然沒法正常運行。【c5soft注:dpr中包含midasLib.dcu單元發佈時就不用midas.dll了】
3、結束語
經過使用Delphi中TClientDataSet控件,既實現了應用程序可完全脫離數據庫驅動程序,也實現了常規數據集控件簡單易用的特性,爲編寫"瘦"數據庫應用程序提供了一種技術方法和手段。
上述程序在Pwindows98,Delphi5下測試經過。
TClientDataSet在三層結構中,TClientDataSet的地位是不可估量的,她的使用正確與否,是十分關鍵的,本文從如下幾個方面闡述她的使用,但願對你有所幫助.
1.動態索引
procedure TForm1.DBGrid1TitleClick(Column: TColumn);
begin
if (not column.Field is Tblobfield) then//Tblobfield不能索引,二進制
ClientDataSet1.IndexFieldNames:=column.Field.FieldName;
end;
2.多層結構中主從表的實現
設主表ClientDataSet1.packetrecord爲-1,全部記錄
設從表ClientDataSet1.packetrecord爲0,當前記錄
3.Taggregates使用
(1)在字段編輯中add new field類型爲aggregates
後設置expression(表達試)
設置active:=true便可
使用dbedit的field爲前者便可
(2)使用Aggergates屬性add設計表達試
調用
showmessage(floattostr(ClientDataSet1.Aggregates.Count));
showmessage(ClientDataSet1.Aggregates.Items[0].Value);
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內容爲空
ClientDataSet1.Close;
ClientDataSet1.CommandText:=edit1.Text;//即sql內容
ClientDataSet1.Open;
對於沒有應用服務器設置filter 如:country like 'A%'
filtered=true可實現sql功能
(2)有參數
如服務端query的sql爲
select * from animals
where name like :dd
則:客戶端ClientDataSet
var
pm:Tparam;
begin
ClientDataSet1.Close;
ClientDataSet1.ProviderName:='DataSetProvider1';
pm:=Tparam.Create(nil);
pm.Name:='dd';
pm.DataType:=ftString;
ClientDataSet1.Params.Clear;
ClientDataSet1.Params.AddParam(pm);
ClientDataSet1.Params.ParamByName('dd').AsString:=edit1.Text ;
ClientDataSet1.Open;
pm.Free;
end;
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處理速度的一個因素
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;
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
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快
發佈