国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

多層數(shù)據(jù)庫開發(fā)六:什么是數(shù)據(jù)集

2019-11-18 18:11:18
字體:
供稿:網(wǎng)友
第六章 什么是數(shù)據(jù)集
  Delphi 4中有四種類型的標(biāo)準(zhǔn)數(shù)據(jù)集構(gòu)件,分別是TTable、TQuery、TStoredPRoc和TClientDataSet。這些數(shù)據(jù)集構(gòu)件都是從一個(gè)共同的基類TDataSet繼承下來的,其中,只有TClientDataSet是直接從TDataSet繼承下來的,而TTable、TQuery、TStoredProc的直接上級(jí)是TDBDataSet,TDBDataSet的上級(jí)是TBDEDataSet,TBDEDataSet 的上級(jí)才是TDataSet。這幾個(gè)類之間的繼承關(guān)系可以用圖6.1來表示。
  圖6.1 數(shù)據(jù)集的繼承關(guān)系
  TDataSet是所有數(shù)據(jù)集的抽象基類,它的大部分屬性和方法是虛擬的或抽象的。所謂虛擬的方法,是指這些方法可以被派生類重載。所謂抽象的方法,是指這些方法只有聲明,沒有定義,派生類必須給出定義后才能調(diào)用這些方法,不同的派生類可以有不同的定義。
  由于TDataSet中包含抽象的方法,您不能直接創(chuàng)建它的實(shí)例,否則會(huì)引起運(yùn)行期錯(cuò)誤。
  如果從功能上劃分,TDataSet的屬性和方法可以分為這么幾大塊:打開和關(guān)閉數(shù)據(jù)集、瀏覽記錄、編輯數(shù)據(jù)、書簽管理、控制連接、訪問字段、記錄緩沖區(qū)管理、過濾、事件。
6.1 打開和關(guān)閉數(shù)據(jù)集
  在對(duì)數(shù)據(jù)集進(jìn)行任何操作之前,首先要打開數(shù)據(jù)集。要打開數(shù)據(jù)集,可以把Active屬性設(shè)為True,例如:
  CustTable.Active := True;
  也可以調(diào)用Open函數(shù),例如:CustQuery.Open;
  要關(guān)閉數(shù)據(jù)集,可以把Active屬性設(shè)為False或者調(diào)用Close函數(shù)。
6.2 數(shù)據(jù)集的狀態(tài)
  數(shù)據(jù)集的狀態(tài)(State屬性)決定了當(dāng)前能夠?qū)?shù)據(jù)集進(jìn)行的操作,例如,當(dāng)數(shù)據(jù)集已經(jīng)關(guān)閉,它的狀態(tài)是dsInactive,此時(shí)就不能訪問數(shù)據(jù)集的任何數(shù)據(jù)。
6.2.1 State屬性
  State屬性是只讀的,下面列出了State屬性可能的值:
.dsInactive 數(shù)據(jù)集已關(guān)閉,不能訪問它的數(shù)據(jù);
.dsBrowse 數(shù)據(jù)集已打開,可以瀏覽數(shù)據(jù)但不能修改數(shù)據(jù);
.dsEdit 此時(shí)為編輯狀態(tài),可以修改數(shù)據(jù);
.dsInsert 此時(shí)可以插入一條新的記錄;
.dsSetKey 只適用于TTable和TClientDataSet,此時(shí)可以設(shè)置范圍和鍵值,并且可以調(diào)用GotoKey函數(shù);
.dsCalcFields 正在處理OnCalcFields事件,此時(shí)不能修改非計(jì)算字段的值;
.dsCurValue 內(nèi)部使用;
.dsNewValue 內(nèi)部使用;
.dsOldValue 內(nèi)部使用;
.dsFilter 正在進(jìn)行過濾操作。
  當(dāng)一個(gè)數(shù)據(jù)集剛剛打開的時(shí)候,它的State屬性被設(shè)為dsBrowse,以后,State屬性的值會(huì)隨著應(yīng)用程序的操作自動(dòng)變化。
  要使數(shù)據(jù)集進(jìn)入dsBrowse、dsEdit、dsInsert或dsSetKey狀態(tài),就得調(diào)用相應(yīng)的方法。
   例如,要使數(shù)據(jù)集CustTable進(jìn)入dsInsert狀態(tài),程序示例如下:
Procedure TForm1.InsertButtonClick(Sender: TObject);
Begin
CustTable.Insert;{進(jìn)入dsInsert狀態(tài)}
AddressPromptDialog.ShowModal;
If AddressPromptDialog.ModalResult := mrOK then
CustTable.Post; {恢復(fù)為dsBrowse狀態(tài)}
Else
CustTable.Cancel; {恢復(fù)為dsBrowse狀態(tài)}
End;
  從上面這個(gè)例子可以看出,有些操作會(huì)使數(shù)據(jù)集自動(dòng)變成dsBrowse狀態(tài),例如,調(diào)用Post函數(shù)如果成功的話,數(shù)據(jù)集就恢復(fù)為dsBrowse狀態(tài),如果調(diào)用Post沒有成功,數(shù)據(jù)集仍然保持原來的狀態(tài)。調(diào)用Cancel也能使數(shù)據(jù)集恢復(fù)為dsBrowse狀態(tài)。
  如果把Active屬性設(shè)為False,或者調(diào)用Close,將使數(shù)據(jù)集進(jìn)入dsInactive狀態(tài)。例如,下面兩行代碼是等價(jià)的:
  CustTable.Active := False;
  CustTable.Close;
  有些狀態(tài)如dsCalcFields、dsCurValue、dsNewValue、dsOldValue和dsFilter不能被應(yīng)用程序所控制,而是由數(shù)據(jù)集本身根據(jù)需要自動(dòng)設(shè)置的。例如,當(dāng)正在處理OnCalcFields事件時(shí),就自動(dòng)進(jìn)入dsCalcFields狀態(tài)。當(dāng)退出處理OnCalcFields事件的句柄時(shí),數(shù)據(jù)集自動(dòng)恢復(fù)成原先的狀態(tài)。
  當(dāng)數(shù)據(jù)集的狀態(tài)發(fā)生改變時(shí),會(huì)觸發(fā)TDataSource構(gòu)件的OnStateChange事件,如果這個(gè)TDataSource構(gòu)件的DataSet屬性指定了這個(gè)數(shù)據(jù)集的話。
  下面詳細(xì)介紹數(shù)據(jù)集的各種狀態(tài)以及怎樣進(jìn)入這些狀態(tài)。
6.2.2 dsInactive狀態(tài)
  當(dāng)數(shù)據(jù)集已關(guān)閉時(shí),就處于dsInactive狀態(tài)。此時(shí),不能訪問它的任何數(shù)據(jù)。
  要使數(shù)據(jù)集進(jìn)入dsInactive狀態(tài),可以把Active屬性設(shè)為False,或者調(diào)用Close。在數(shù)據(jù)集將要關(guān)閉之前,會(huì)觸發(fā)BeforeClose事件。當(dāng)數(shù)據(jù)集剛剛關(guān)閉,會(huì)觸發(fā)AfterClose事件。如果在數(shù)據(jù)集處于dsEdit或dsInsert狀態(tài)時(shí)調(diào)用Close,應(yīng)當(dāng)在處理BeforeClose事件的句柄中提示用戶是認(rèn)可還是取消。程序示例如下:
Procedure CustTable.VerifyBeforeClose(DataSet: TDataSet)
Begin
If (CustTable.State = dsEdit) or (CustTable.State = dsInsert) then
Begin
If MessageDlg('認(rèn)可修改嗎?', mtConfirmation, mbYesNo, 0) = mrYes then
CustTable.Post;
ElseCustTable.Cancel;
End;
End;
6.2.3 dsBrowse狀態(tài)
  當(dāng)一個(gè)數(shù)據(jù)集剛剛打開的時(shí)候,數(shù)據(jù)集總是處于dsBrowse狀態(tài),此時(shí),可以顯示數(shù)據(jù)集中的記錄,但不能編輯和插入記錄。
  dsBrowse狀態(tài)可以認(rèn)為是數(shù)據(jù)集的基本狀態(tài),在此狀態(tài)下,可以進(jìn)入其他狀態(tài)。例如,調(diào)用Insert或Append函數(shù)將使數(shù)據(jù)集的狀態(tài)從dsBrowse變成dsInsert(當(dāng)然,這還取決于其他因素,如CanModify屬性的值),調(diào)用SetKey將使數(shù)據(jù)集從dsBrowse變成dsSetKey狀態(tài)。
  TDataSet有兩個(gè)方法可以使數(shù)據(jù)集回到dsBrowse狀態(tài),一個(gè)是Cancel,它將取消當(dāng)前正在進(jìn)行的編輯、插入、搜索等操作,使數(shù)據(jù)集回到dsBrowse狀態(tài)。另一個(gè)是Post,它將試圖把修改了的數(shù)據(jù)保存到數(shù)據(jù)集中,如果成功的話,數(shù)據(jù)集將回到dsBrowse狀態(tài),如果沒有成功,數(shù)據(jù)集仍然保持原先的狀態(tài)。
6.2.4 dsEdit狀態(tài)
  如果應(yīng)用程序要修改數(shù)據(jù)集的數(shù)據(jù),必須首先進(jìn)入dsEdit狀態(tài)。要進(jìn)入dsEdit狀態(tài),可以調(diào)用Edit。不過,調(diào)用Edit并不能保證一定能進(jìn)入dsEdit狀態(tài),這還取決于CanModify屬性的值。如果這個(gè)屬性返回True的話,表示數(shù)據(jù)集是可以讀和寫的。
  對(duì)于TTable構(gòu)件來說,如果ReadOnly屬性設(shè)為True,CanModify屬性肯定返回False。對(duì)于TQuery構(gòu)件來說,如果RequestLive屬性設(shè)為False,CanModify屬性肯定返回False。
  即使數(shù)據(jù)集進(jìn)入了dsEdit狀態(tài),也并不意味著用戶就一定能修改數(shù)據(jù),數(shù)據(jù)控件的ReadOnly屬性還必須設(shè)為False。此外,對(duì)于SQL數(shù)據(jù)庫來說,用戶能不能修改數(shù)據(jù)還取決于用戶有沒有修改數(shù)據(jù)的權(quán)限。
  要從dsEdit狀態(tài)返回到dsBrowse狀態(tài),可以調(diào)用Cancel、Post或Delete函數(shù),其中,如果Post和Delete沒有調(diào)用成功的話,就仍然保持dsEdit狀態(tài)。
  在數(shù)據(jù)控件中,當(dāng)用戶修改了數(shù)據(jù)后把輸入焦點(diǎn)移走,就相當(dāng)于調(diào)用Post函數(shù),將使數(shù)據(jù)集回到dsBrowse狀態(tài)。
6.2.5 dsInsert狀態(tài)
  如果應(yīng)用程序要插入新的記錄,必須首先進(jìn)入dsInsert狀態(tài)。要進(jìn)入dsInsert狀態(tài),可以調(diào)用Insert或Append函數(shù)。不過,調(diào)用Insert或Append并不能保證一定能進(jìn)入dsInsert狀態(tài),這還取決于CanModify屬性的值是否返回True。
  即使數(shù)據(jù)集進(jìn)入了dsInsert狀態(tài),也并不意味著用戶就一定能插入記錄,數(shù)據(jù)控件的ReadOnly屬性還必須設(shè)為False。此外,對(duì)于SQL數(shù)據(jù)庫來說,用戶能不能插入記錄還取決于用戶有沒有修改數(shù)據(jù)的權(quán)限。
  要從dsInsert狀態(tài)返回到dsBrowse狀態(tài),可以調(diào)用Cancel、Post或Delete函數(shù),其中,如果Post沒有調(diào)用成功的話,就仍然保持dsInsert狀態(tài)。
  在數(shù)據(jù)控件中,當(dāng)用戶修改了數(shù)據(jù)后把輸入焦點(diǎn)移走,就相當(dāng)于調(diào)用Post,將使數(shù)據(jù)集回到dsBrowse狀態(tài)。
6.2.6 dsSetKey狀態(tài)
  可以調(diào)用Locate、Lookup在數(shù)據(jù)集中搜索特定的記錄。對(duì)于TTable構(gòu)件來說,還可以調(diào)用GotoKey、GotoNearest、FindKey或FindNearest在表格中搜索特定的記錄。在調(diào)用上述方法之前,必須首先使數(shù)據(jù)集進(jìn)入dsSetKey狀態(tài)。要使數(shù)據(jù)集進(jìn)入dsSetKey狀態(tài),可以調(diào)用SetKey。調(diào)用了上述方法后,數(shù)據(jù)集又回到dsBrowse狀態(tài)。
  另外,可以對(duì)數(shù)據(jù)集進(jìn)行過濾。對(duì)于TTable構(gòu)件來說,還可以預(yù)先設(shè)置范圍。在進(jìn)行過濾和范圍操作前,也要首先進(jìn)入dsSetKey狀態(tài)。
6.2.7 dsCalcFields狀態(tài)
  當(dāng)OnCalcFields事件被觸發(fā)時(shí),就會(huì)使數(shù)據(jù)集進(jìn)入dsCalcFields狀態(tài)。在處理OnCalcFields事件的句柄中,應(yīng)當(dāng)給出“計(jì)算字段”的值。
  在dsCalcFields狀態(tài)下,除了“計(jì)算字段”外,應(yīng)用程序不能修改其他字段的值,因?yàn)槿绻渌侄蔚闹蛋l(fā)生變化,又會(huì)導(dǎo)致OnCalcFields事件被觸發(fā),從而導(dǎo)致無限循環(huán)。
  當(dāng)OnCalcFields事件處理完畢,數(shù)據(jù)集又回到dsBrowse狀態(tài)。
6.2.8 dsFilter狀態(tài)
  當(dāng)OnFilterRecord事件被觸發(fā)時(shí),就會(huì)使數(shù)據(jù)集進(jìn)入dsFilter狀態(tài)。在此狀態(tài)下,不允許修改數(shù)據(jù)集的記錄,否則,過濾就無法正確執(zhí)行。
  當(dāng)OnFilterRecord事件處理完畢,數(shù)據(jù)集就回到dsBrowse狀態(tài)。
6.2.9 dsNewValue、dsOldValue或dsCurValue
  在允許緩存更新的情況下,當(dāng)用戶修改數(shù)據(jù)集的記錄時(shí),數(shù)據(jù)集有可能會(huì)進(jìn)入dsNewValue、dsOldValue或dsCurValue狀態(tài)。在這三種狀態(tài)下,可以通過字段(TField)的NewValue、OldValue或CurValue屬性來訪問當(dāng)時(shí)的值。
  上述三個(gè)狀態(tài)是由Delphi 4內(nèi)部使用的,應(yīng)用程序無法主動(dòng)進(jìn)入上述三種狀態(tài)。
6.3 瀏 覽 記 錄
  每個(gè)活動(dòng)的數(shù)據(jù)集都有一個(gè)指針,指向當(dāng)前記錄。很多對(duì)數(shù)據(jù)集的操作都是針對(duì)當(dāng)前記錄,許多數(shù)據(jù)控件也只顯示當(dāng)前記錄的數(shù)據(jù),因此,在數(shù)據(jù)庫應(yīng)用程序中知道當(dāng)前記錄的位置是非常重要的。
  數(shù)據(jù)庫應(yīng)用程序往往要改變當(dāng)前記錄的位置,這時(shí)候就要用到下面這些方法:
.First 使第一條記錄成為當(dāng)前記錄;
.Last 使最后一條記錄成為當(dāng)前記錄;
.Next 使下一條記錄成為當(dāng)前記錄;
.Prior 使前一條記錄成為當(dāng)前記錄;
.MoveBy 使距離當(dāng)前記錄若干行的記錄成為當(dāng)前記錄。
  此外,Delphi 4中有一個(gè)TDBNavigator構(gòu)件,專門用來瀏覽記錄,它把上述方法用按鈕來實(shí)現(xiàn)。
  除了上述方法外,TDataSet中還有兩個(gè)只讀的布爾類型的屬性用來判斷當(dāng)前記錄的位置,一個(gè)是Bof,如果這個(gè)屬性返回True,表示現(xiàn)在已到了數(shù)據(jù)集的開始位置。另一個(gè)是Eof,如果這個(gè)屬性返回True,表示現(xiàn)在已到了數(shù)據(jù)集的末尾。
6.3.1 First和Last
  調(diào)用First函數(shù)能夠使數(shù)據(jù)集的第一條記錄成為當(dāng)前記錄,并且把Bof屬性設(shè)為True。如果第一條記錄已經(jīng)是當(dāng)前記錄了,F(xiàn)irst就什么也不干。程序示例如下:
  CustTable.First;
  調(diào)用Last函數(shù)能夠使數(shù)據(jù)集的最后一條記錄成為當(dāng)前記錄,并且把Eof屬性設(shè)為True。如果最后一條記錄已經(jīng)是當(dāng)前記錄,Last就什么也不干。程序示例如下:
  CustTable.Last;
  用TDBNavigator構(gòu)件實(shí)現(xiàn)的導(dǎo)航器上有兩個(gè)按鈕,分別對(duì)應(yīng)著First和Last。
6.3.2 Next和Prior
  調(diào)用Next函數(shù)能夠使下一條記錄成為當(dāng)前記錄。如果當(dāng)前記錄已經(jīng)是數(shù)據(jù)集的最后一條記錄,Next就什么也不干。程序示例如下:
  CustTable.Next;
  調(diào)用Prior能夠使前一條記錄成為當(dāng)前記錄。如果當(dāng)前記錄已經(jīng)是數(shù)據(jù)集的第一條記錄,Prior就什么也不干。程序示例如下:
  CustTable.Prior;
6.3.3 MoveBy
  調(diào)用MoveBy函數(shù)使數(shù)據(jù)集中的另一條記錄成為當(dāng)前記錄,該記錄距原先的當(dāng)前記錄若干行。MoveBy需要傳遞一個(gè)參數(shù),指定相隔的行數(shù),正數(shù)表示向記錄編號(hào)增大的方向移動(dòng),負(fù)數(shù)表示向記錄編號(hào)減小的方向移動(dòng)。程序示例如下:
  CustTable.MoveBy(-2);
  MoveBy返回實(shí)際移動(dòng)的行數(shù),返回值與傳遞給MoveBy的參數(shù)有可能不同。
  注意:在多用戶環(huán)境下,其他用戶有可能正在修改、插入或刪除記錄,這樣,一條記錄原來距當(dāng)前記錄是5行,現(xiàn)在有可能變?yōu)?行和6行,甚至該記錄都不存在了,因?yàn)槠渌脩粜薷脑撚涗浀臄?shù)據(jù)或刪除了該記錄。
6.3.4 Eof和Bof屬性
  TDataSet有兩個(gè)只讀的屬性Eof和Bof,分別用于判斷是否到了數(shù)據(jù)集的末尾和開頭。在遍歷數(shù)據(jù)集的所有記錄時(shí)經(jīng)常要用到這兩個(gè)屬性。
  如果Eof屬性返回True,表示現(xiàn)在已到了數(shù)據(jù)集的末尾。
  進(jìn)行下列操作時(shí)會(huì)把Eof屬性設(shè)為True:
.打開一個(gè)空的數(shù)據(jù)集;
.調(diào)用了Last;
.調(diào)用了Next,而現(xiàn)在已經(jīng)在數(shù)據(jù)集的最后一條記錄;
.調(diào)用了SetRange,而范圍是無效的。
  除了上述情況外,Eof屬性都將返回False。
  Eof屬性通常用在一個(gè)循環(huán)中,每調(diào)用一次Next就要判斷一下Eof屬性,以避免對(duì)不存在的記錄進(jìn)行操作。程序示例如下:
CustTable.DisableControls;
Try
CustTable.First;
While not CustTable.EOF Do
Begin
...
CustTable.Next;
End;
Finally
CustTable.EnableControls;
End;
上述代碼同時(shí)演示了在遍歷數(shù)據(jù)集的所有記錄時(shí)怎樣暫時(shí)禁止數(shù)據(jù)控件跟著刷新。在遍歷數(shù)據(jù)集的所有記錄前應(yīng)當(dāng)調(diào)用DisableControls禁止刷新,這樣能夠加快遍歷的速度,因?yàn)樗⑿乱彩且〞r(shí)間的。遍歷結(jié)束后,應(yīng)當(dāng)調(diào)用EnableControls恢復(fù)刷新。
  EnableControls最好在Try...Finally結(jié)構(gòu)的Finally部分調(diào)用,這樣能保證即使在遍歷時(shí)出現(xiàn)異常,也能保證刷新能得到恢復(fù)。
  如果Bof屬性返回True,表示現(xiàn)在已到了數(shù)據(jù)集的開頭。
  進(jìn)行下列操作時(shí)會(huì)把Bof屬性設(shè)為True:
.打開一個(gè)非空的數(shù)據(jù)集;
.調(diào)用了First;
.調(diào)用了Prior,而現(xiàn)在已經(jīng)在數(shù)據(jù)集的第一條記錄。
  除了上述情況外,Bof屬性都將返回False。與Eof屬性一樣,Bof屬性通常用在一個(gè)循環(huán)中,每調(diào)用一次Prior就要判斷一下Bof屬性,以避免對(duì)不存在的記錄進(jìn)行操作。程序示例如下:
CustTable.DisableControls;
Try
While not CustTable.BOF Do
Begin
...
CustTable.Prior;
End;
Finally
CustTable.EnableControls;
End;
6.4 書 簽
  書簽的作用是在數(shù)據(jù)集的某個(gè)位置做一個(gè)標(biāo)記,以后可以快速方便地回到那個(gè)位置。TDataSet中提供了若干個(gè)屬性和方法用于管理書簽。
  如果讀Bookmark屬性,返回當(dāng)前記錄的書簽。如果寫B(tài)ookmark屬性,它能使一個(gè)指定的書簽成為當(dāng)前書簽。
  TDataSet中有關(guān)書簽的幾個(gè)函數(shù)都是虛擬的,TDataSet的派生類TBDEDataSet重新定義了這些方法,包括:
.BookmarkValid判斷某個(gè)書簽是否合法;
.CompareBookmarks比較兩個(gè)書簽是否相同;
.GetBookmark創(chuàng)建一個(gè)書簽來標(biāo)記當(dāng)前記錄;
.GotoBookmark回到用GetBookmark標(biāo)記的位置;
.FreeBookmark刪除一個(gè)書簽。
  要?jiǎng)?chuàng)建一個(gè)書簽,首先要聲明一個(gè)TBookmark類型的變量,然后調(diào)用GetBookmark函數(shù)創(chuàng)建一個(gè)標(biāo)記當(dāng)前記錄的書簽。TBookmark類型的變量實(shí)際上是一個(gè)無類型的指針。
  在調(diào)用GotoBookmark之前,最好先調(diào)用BookmarkValid判斷書簽是否合法,因?yàn)闀灅?biāo)記的記錄有可能已刪掉。如果BookmarkValid返回True,說明書簽是合法的,可以調(diào)用GotoBookmark跳轉(zhuǎn)到書簽標(biāo)記的位置。
可以調(diào)用CompareBookmarks比較兩個(gè)書簽是否相同,如果兩個(gè)書簽不同,這個(gè)函數(shù)就返回1。如果兩個(gè)書簽相同或者都是NIL,這個(gè)函數(shù)就返回0。
  GotoBookmark需要傳遞一個(gè)參數(shù),即書簽。
  FreeBookmark用于刪除一個(gè)書簽。當(dāng)一個(gè)書簽已用不到時(shí),應(yīng)當(dāng)及時(shí)刪除它,因?yàn)闀炓彩且环N資源。
  下面這段代碼演示了書簽的用法:
Procedure DoSomething (const Tbl: TTable)varBookmark: TBookmark;
Begin
Bookmark := Tbl.GetBookmark;
Tbl.DisableControls;
Try
Tbl.First;
While not Tbl.EOF Do
Begin
...
Tbl.Next;
End;
Finally
Tbl.GotoBookmark(Bookmark);
Tbl.EnableControls;
Tbl.FreeBookmark(Bookmark);
End;
End;
6.5 搜索特定的記錄
  可以調(diào)用Locate和Lookup函數(shù)在數(shù)據(jù)集中搜索特定的記錄。
   Locate用于在數(shù)據(jù)集中定位一條特定的記錄,并使該記錄成為當(dāng)前記錄。Locate需要傳遞三個(gè)參數(shù),第一個(gè)是KeyFields參數(shù),用于指定要按哪些字段搜索,第二個(gè)是KeyValues參數(shù),用于指定每個(gè)字段相應(yīng)的值,第三個(gè)是Options參數(shù),用于設(shè)置搜索選項(xiàng)。
  下面這個(gè)例子搜索Company字段的值為“Professional Ltd.”的記錄:
var
LocateSuccess: Boolean;
SearchOptions: TLocateOptions;
Begin
SearchOptions := [loPartialKey];
LocateSuccess := CustTable.Locate('Company', 'Professional Ltd.',SearchOptions);
End;
  如果Locate找到了一條符合條件的記錄,就把該記錄變?yōu)楫?dāng)前記錄,并返回True。如果Locate沒有找到匹配的記錄,就返回False。
  對(duì)于Locate來說,KeyFields參數(shù)指定的字段越多,搜索的條件就越精確。如果KeyFields參數(shù)需要指定多個(gè)字段,彼此之間要用分號(hào)分開。由于字段的數(shù)據(jù)類型可能各不相同,因此,KeyValues是一個(gè)Variant類型的參數(shù)。如果KeyFields參數(shù)指定了多個(gè)字段,KeyValues參數(shù)必須是一個(gè)可變類型的數(shù)組。程序示例如下:
  With CustTable Do
   Locate('Company;Contact;Phone', VarArrayOf(['Sight Diver','P']), loPartialKey);
   Lookup與Locate非常相似,也是在數(shù)據(jù)集中搜索特定的記錄。不同的是,如果找到匹配的記錄,Lookup能返回該記錄中若干個(gè)字段的值。
   Lookup需要傳遞三個(gè)參數(shù),第一個(gè)是KeyFields參數(shù),用于指定要按哪些字段搜索,第二個(gè)是KeyValues參數(shù),用于指定每個(gè)字段相應(yīng)的值,第三個(gè)是ResultFields參數(shù),用于指定要返回哪些字段的值。
  下面這個(gè)例子在CustTable中搜索Company字段的值為“Professional Ltd.”的記錄,并返回Company、Contact、Phone等字段的值:
var
LookupResults: Variant;
Begin
With CustTable Do
LookupResults := Lookup('Company', 'Professional Divers, Ltd.', 'Company;Contact; Phone');
End;
  如果ResultFields參數(shù)指定了多個(gè)字段,Lookup返回一個(gè)可變類型的數(shù)組。如果沒有找到匹配的記錄,Lookup將返回一個(gè)空的數(shù)組。程序示例如下:
var
LookupResults: Variant;
Begin
With CustTable Do
LookupResults := Lookup('Company; City', VarArrayOf(['Sight Diver',
  'Christiansted']), 'Company; Addr1; Addr2; State; ZEnd;
6.6 過 濾
  一個(gè)應(yīng)用程序往往只對(duì)數(shù)據(jù)集的部分記錄感興趣,例如,可能只對(duì)一個(gè)客戶表中來自廣東的客戶感興趣。這種情況下,可以用過濾技術(shù)把符合特定條件的記錄過濾出來。
  不過,對(duì)于一個(gè)字段很多的數(shù)據(jù)集來說,最好還是使用查詢。
6.6.1 允許過濾
  要對(duì)數(shù)據(jù)集進(jìn)行過濾,首先要指定過濾條件,并設(shè)置FilterOptions屬性設(shè)置有關(guān)選項(xiàng)(可選),然后把Filtered屬性設(shè)為True。以后如果不想進(jìn)行過濾,只要把Filtered屬性設(shè)為False。
  要指定過濾條件有兩種方式:一是設(shè)置Filter屬性,二是在處理OnFilterRecord事件的句柄中給出過濾條件。
  Filter屬性適合于在運(yùn)行期使用,它能夠動(dòng)態(tài)地指定過濾條件,能夠根據(jù)需要改變過濾條件。不過,F(xiàn)ilter屬性是一個(gè)字符串,過濾條件相對(duì)比較簡(jiǎn)單。雖然可以用運(yùn)算符構(gòu)成復(fù)合的條件表達(dá)式,但只限于幾個(gè)常見的運(yùn)算符。更主要的是,用Filter屬性指定的表達(dá)式中只能出現(xiàn)數(shù)據(jù)集中已有的字段名和常量,不能出現(xiàn)其他數(shù)據(jù)。
  而OnFilterRecord事件則靈活得多,它能夠在設(shè)計(jì)期就指定好過濾條件。而在處理OnFilterRecord事件的句柄中,可以任意指定過濾條件,過濾條件可以很復(fù)雜。
6.6.2 Filter屬性
  Filter屬性是一個(gè)字符串,可以這樣設(shè)置Filter屬性:
  Dataset1.Filter := '''State'' = ''CA''';
  也可以這樣設(shè)置Filter屬性:
  Dataset1.Filter := Edit1.Text;
  上面這行代碼允許讓用戶自己輸入過濾條件。甚至還可以把上述兩行代碼結(jié)合起來:
  Dataset1.Filter := '''State'' = ' + Edit1.Text;
  設(shè)置了過濾條件后,只要把Filtered屬性設(shè)為True,過濾即有效。
  可以用比較和邏輯運(yùn)算符構(gòu)造復(fù)合的過濾條件,這些運(yùn)算符包括:
. <小于;
. >大于;
. >=大于等于;
. <=小于等于;
.=等于;
. <>不等于;
.AND兩邊的表達(dá)式都必須為True;
.NOT表達(dá)式不能為True;
.OR兩個(gè)表達(dá)式只要有一個(gè)為True。
  下面這個(gè)例子用AND運(yùn)算符限制CustNo字段必須大于1400且小于1500:
  (CustNo > 1400) AND (CustNo < 1500);
  注意:在Filtered屬性設(shè)為True的情況下,用戶修改、插入的記錄有可能不符合過濾的條件,這時(shí)候,會(huì)拒絕接受與過濾條件矛盾的記錄。
6.6.3 OnFilterRecord事件
  在Filtered屬性設(shè)為True的情況下,數(shù)據(jù)集中的每條記錄都會(huì)觸發(fā)OnFilterRecord事件,這樣,就有機(jī)會(huì)決定是否要把記錄過濾。
  處理OnFilterRecord事件的句柄中有一個(gè)布爾類型的Accept參數(shù),把這個(gè)參數(shù)設(shè)為True表示接受此記錄,把這個(gè)參數(shù)設(shè)為False表示把此記錄過濾掉。程序示例如下:
Procedure TForm1.Table1FilterRecord(DataSet: TDataSet;
var Accept: Boolean);
Begin
Accept := DataSet['State'] = 'CA';
End;
  上面這個(gè)例子的意思是,只有State字段的值為CA的記錄才被接受。
  注意:由于數(shù)據(jù)集的每條記錄都會(huì)觸發(fā)OnFilterRecord事件,因此,處理OnFilterRecord事件的代碼要盡可能地簡(jiǎn)短,尤其是對(duì)一個(gè)有很多條記錄的大型數(shù)據(jù)集。
  有時(shí)候,程序需要按多種不同的過濾條件進(jìn)行過濾,可以建立多個(gè)處理OnFilterRecord事件的句柄,然后在運(yùn)行期動(dòng)態(tài)地切換事件句柄,程序示例如下:
  DataSet1.OnFilterRecord := NewYorkFilter;Refresh;
6.6.4 設(shè)置過濾選項(xiàng)
  FilterOptions屬性用于設(shè)置過濾的選項(xiàng)。這個(gè)屬性是一個(gè)集合,可以是空集(默認(rèn)),也可以包含下列元素:
.foCaseInsensitive比較字符串時(shí)忽略大小寫;
.foPartialCompare對(duì)于字符串類型的字段必須全字匹配,不允許部分匹配。
  例如,為了在比較State字段時(shí)忽略大小寫,可以這樣設(shè)置:
  FilterOptions := [foCaseInsensitive];
  Filter := '''State'' = ''CA''';
6.6.5 在過濾后的數(shù)據(jù)集中瀏覽記錄
  過濾后的數(shù)據(jù)集實(shí)際上是原來的數(shù)據(jù)集的一個(gè)子集。TDataSet提供了四個(gè)方法用于在過濾后的數(shù)據(jù)集中瀏覽記錄,它們是:
.FindFirst使過濾后的數(shù)據(jù)集中的第一條記錄成為當(dāng)前記錄;
.FindLast使過濾后的數(shù)據(jù)集中的最后一條記錄成為當(dāng)前記錄;
.FindNext使過濾后的數(shù)據(jù)集中的下一條記錄成為當(dāng)前記錄;
.FindPrior使過濾后的數(shù)據(jù)集中的前一條記錄成為當(dāng)前記錄。
  上述四個(gè)方法如果調(diào)用成功,就返回True,否則,就返回False。可以檢查一個(gè)只讀的Found屬性,看看上次調(diào)用是否成功。
  如果通過Filter屬性或OnFilterRecord事件設(shè)置了過濾條件,而Filtered屬性設(shè)為False,調(diào)用上述四個(gè)方法時(shí)會(huì)自動(dòng)暫時(shí)允許過濾,然后移動(dòng)當(dāng)前記錄的位置,最后又禁止過濾。換句話說,上述四個(gè)方法可以不理會(huì)Filtered屬性是怎樣設(shè)置的。
  如果沒有設(shè)置過濾條件,上述四個(gè)方法即相當(dāng)于First、Last、Next和Prior。
6.7 修 改 數(shù) 據(jù)
  TDataSet中提供了一些方法用于在數(shù)據(jù)集中更新、插入和刪除記錄,它們是:
.Edit使數(shù)據(jù)集進(jìn)入dsEdit狀態(tài);
.Append在數(shù)據(jù)集的末尾添加一條記錄;
.Insert在數(shù)據(jù)集的當(dāng)前位置插入一條記錄;
.Post試圖把用戶對(duì)數(shù)據(jù)的修改寫到數(shù)據(jù)集中;
.Cancel取消用戶對(duì)數(shù)據(jù)的修改,使數(shù)據(jù)集回到dsBrowse狀態(tài);
.Delete刪除當(dāng)前記錄。
6.7.1 進(jìn)入dsEdit狀態(tài)
  要編輯數(shù)據(jù)集的記錄,首先要進(jìn)入dsEdit狀態(tài)。要進(jìn)入dsEdit狀態(tài),調(diào)用Edit函數(shù)。不過,調(diào)用Edit不一定會(huì)使數(shù)據(jù)集進(jìn)入dsEdit狀態(tài),還取決于CanModify屬性的值。
  一旦數(shù)據(jù)集進(jìn)入了dsEdit狀態(tài),用戶就可以在數(shù)據(jù)控件上修改當(dāng)前記錄的值。當(dāng)用戶把輸入焦點(diǎn)從當(dāng)前記錄上移走,即相當(dāng)于調(diào)用了Post函數(shù)。程序示例如下:
With CustTable Do
Begin
Edit;
FieldValues['CustNo'] := 1234;
Post;
End;
  要取消當(dāng)前未決的修改,用戶可以按ESC鍵或單擊用TDBNavigator構(gòu)件實(shí)現(xiàn)的導(dǎo)航器上的Cancel按鈕。
  在使用緩存更新技術(shù)(CachedUpdates屬性設(shè)為True)的情況下,調(diào)用Post只是把數(shù)據(jù)寫到緩存中,而不是直接寫到數(shù)據(jù)集中。要把緩存中的數(shù)據(jù)寫到數(shù)據(jù)集中,需調(diào)用ApplyUpdates函數(shù)。
6.7.2 插入新的記錄
  要在數(shù)據(jù)集中插入新的記錄,首先要進(jìn)入dsInsert狀態(tài)。要進(jìn)入dsInsert狀態(tài),可以調(diào)用Insert或Append函數(shù)。不過,調(diào)用Insert或Append不一定會(huì)使數(shù)據(jù)集進(jìn)入dsInsert狀態(tài),還取決于CanModify屬性的值。
  一旦進(jìn)入了dsInsert狀態(tài),用戶就可以在數(shù)據(jù)控件(一般是TDBGrid)中插入一條新的記錄,并給這條記錄輸入數(shù)據(jù)。
  如果要通過編程來插入新的記錄,就要注意Insert和Append的區(qū)別。Insert將把一條新的記錄插入到當(dāng)前記錄的前面,而Append將把一條新的記錄添加到數(shù)據(jù)集的末尾。
  插入了新的記錄后,應(yīng)當(dāng)調(diào)用Post或在CachedUpdates屬性設(shè)為True的情況下調(diào)用ApplyUpdates把新的記錄寫到數(shù)據(jù)集中。
  如果數(shù)據(jù)集是已建立了索引的Paradox或dBASE表,新記錄將自動(dòng)移到恰當(dāng)?shù)奈恢谩?BR>  如果數(shù)據(jù)集沒有建立索引,新記錄就插入到數(shù)據(jù)集的當(dāng)前位置(Insert)或末尾(Append)。
6.7.3 刪除記錄
  調(diào)用Delete函數(shù)將刪除當(dāng)前記錄,并且使數(shù)據(jù)集回到dsBrowse狀態(tài)。如果窗體上有TDBNavigator構(gòu)件的話,用戶可以單擊導(dǎo)航器上的“Delete”按鈕刪除當(dāng)前記錄。當(dāng)前記錄被刪除后,下一條記錄就成為當(dāng)前記錄。
  如果刪除的本來就是最后一條記錄,則前一條記錄成為當(dāng)前記錄。
6.7.4 修改整條記錄
  除了TDBGrid和TDBNavigator外,大部分?jǐn)?shù)據(jù)控件只能工作于數(shù)據(jù)集的一個(gè)或幾個(gè)字段,而不是整條記錄。
  不過,TDataSet提供了若干個(gè)方法可以直接修改整條記錄而不是單獨(dú)的字段,這些方法包括:
.AppendRecord類似于Append,但可以給字段賦值,不需要調(diào)用Post;
.InsertRecord類似于Insert,但可以給字段賦值,不需要調(diào)用Post;
.SetFields對(duì)當(dāng)前記錄的字段賦值,需要顯式地調(diào)用Post。
  上述三個(gè)方法都要傳遞一個(gè)TVarRec類型的數(shù)組作為參數(shù),該數(shù)組的每一個(gè)元素對(duì)應(yīng)著一個(gè)字段的值。如果數(shù)組的元素個(gè)數(shù)小于數(shù)據(jù)集的字段個(gè)數(shù),剩下字段的值就是NULL。
  對(duì)于沒有建立索引的數(shù)據(jù)集來說,AppendRecord把一條新的記錄加到數(shù)據(jù)集的末尾。對(duì)于已建立索引的數(shù)據(jù)集來說,新記錄將自動(dòng)移到一個(gè)恰當(dāng)?shù)奈恢谩?BR>  SetFields用于對(duì)當(dāng)前記錄的字段賦值。在調(diào)用SetFields之前,首先要調(diào)用Edit,使數(shù)據(jù)集進(jìn)入dsEdit狀態(tài)。調(diào)用了SetFields后,需要顯式地調(diào)用Post函數(shù)。
  調(diào)用SetFields時(shí),如果您只想對(duì)部分字段賦值,讓其他字段的值保持不變,可以用NULL或NIL去賦值。
  假設(shè)一個(gè)數(shù)據(jù)集中有五個(gè)字段,分別是Name、Capital、Continent、Area和Population,可以這樣對(duì)它們賦值:
CountryTable.InsertRecord(['Japan', 'Tokyo', 'Asia']);
  上述程序在數(shù)據(jù)集中插入了一條新的記錄,并且對(duì)前三個(gè)字段賦了值。現(xiàn)在可以再次對(duì)當(dāng)前記錄賦值,不過,這次只想對(duì)Area字段和Population字段賦值,程序就要這樣寫:
With CountryTable Do
Begin
If Locate('Name', 'Japan', loCaseInsensitive) then
Begin
Edit;
SetFields(NIL, NIL, NIL, 344567, 164700000);
Post;
End;
End;
  注意:此處要用NIL而不是NULL,否則,前三個(gè)字段會(huì)被設(shè)為空。
6.8 事 件
  TDataSet的事件主要分為兩大類,一類是Before系列,另一類是After系列,列表如下:
.BeforeOpen,AfterOpen發(fā)生在數(shù)據(jù)集打開前后;
.BeforeClose,AfterClose發(fā)生在數(shù)據(jù)集關(guān)閉前后;
.BeforeInsert,AfterInsert發(fā)生在插入了一條新的記錄前后;
.BeforeEdit,AfterEdit 發(fā)生在進(jìn)入dsEdit狀態(tài)前后;
.BeforePost,AfterPost 發(fā)生在寫數(shù)據(jù)集的前后;
.BeforeCancel,AfterCancel發(fā)生在取消修改的前后;
.BeforeDelete,AfterDelete發(fā)生在刪除記錄的前后。
  此外,當(dāng)數(shù)據(jù)集中增加了一條新的記錄時(shí)就會(huì)觸發(fā)OnNewRecord事件,當(dāng)“計(jì)算字段”的值需要重算時(shí)將觸發(fā)OnCalcFields事件。
  Before系列的事件常常用來中止操作。例如,當(dāng)調(diào)用Delete函數(shù)試圖刪除當(dāng)前記錄時(shí),在當(dāng)前記錄將要?jiǎng)h除前會(huì)觸發(fā)BeforeDelete事件,可以在處理BeforeDelete事件的句柄中調(diào)用Abort或觸發(fā)一個(gè)異常放棄刪除當(dāng)前記錄,程序示例如下:
Pocedure TForm1.TableBeforeDelete (Dataset: TDataset)
Begin
If MessageDlg('Delete This Record?', mtConfirmation, mbYesNoCancel, 0) <> mrYes Then Abort;
End;
  After系列的事件往往用來在狀態(tài)欄上通知用戶,程序示例如下:
Procedure TForm1.Table1AfterDelete(DataSet: TDataSet);
Begin
StatusBar1.SimpleText := Format('有%d 條記錄',[DataSet.RecordCount]);
End;
  OnCalcFields事件主要用于給出“計(jì)算字段”的值。AutoCalcFields屬性的值決定了什么時(shí)候會(huì)發(fā)生OnCalcFields事件。
  如果AutoCalcFields屬性設(shè)為True,下列情況下會(huì)發(fā)生OnCalcFields事件:
.數(shù)據(jù)集被打開時(shí);
.在數(shù)據(jù)控件中,輸入焦點(diǎn)從一條記錄移到另一條記錄;
.在數(shù)據(jù)控件中,輸入焦點(diǎn)從一個(gè)字段移到另一個(gè)字段;
.當(dāng)前記錄被修改或從數(shù)據(jù)庫中檢索了一條記錄。
  不過,即使AutoCalcFields屬性設(shè)為False,當(dāng)數(shù)據(jù)集中的任意一個(gè)非計(jì)算字段的值發(fā)生變化時(shí)都會(huì)觸發(fā)OnCalcFields事件。
  由于OnCalcFields事件有可能是頻繁發(fā)生的,因此,處理OnCalcFields 事件的代碼要盡可能地簡(jiǎn)短。在AutoCalcFields屬性設(shè)為True的情況下,在處理OnCalcFields事件的句柄中不能修改數(shù)據(jù)集的數(shù)據(jù),因?yàn)橐坏┊?dāng)前記錄被修改,又要觸發(fā)OnCalcFields事件,從而導(dǎo)致無限循環(huán)。例如,假設(shè)您在處理OnCalcFields事件的句柄中調(diào)用了Post,就會(huì)觸發(fā)OnCalcFields事件,導(dǎo)致再次調(diào)用Post,再次觸發(fā)OnCalcFields事件……
6.9 TBDEDataSet
  TBDEDataSet是從TDataSet繼承下來的,它提供了通過BDE(BorlandDatabase Engine)訪問數(shù)據(jù)的能力。這一節(jié)主要介紹TBDEDataSet,讀者應(yīng)當(dāng)對(duì)前面介紹的TDataSet已經(jīng)有了比較深刻的認(rèn)識(shí)。
  與TDataSet一樣,TBDEDataSet也是虛擬的和抽象的,除非您想建立自定義的數(shù)據(jù)集,否則,一般不需要直接用到TBDEDataSet。
  TBDEDataSet重載了TDataSet中涉及記錄導(dǎo)航、索引和書簽的方法,增加了一些處理BLOB字段、緩存更新的屬性、方法和事件。
6.9.1 CacheBlobs屬性
  TBDEDataSet的CacheBlobs屬性用于控制BDE是否把BLOB字段的內(nèi)容放到緩存中。如果這個(gè)屬性設(shè)為True,當(dāng)應(yīng)用程序讀取BLOB字段的值時(shí),BDE將把BLOB字段的內(nèi)容放在緩存中,這樣,當(dāng)應(yīng)用程序下次要讀取這個(gè)字段的值時(shí),就不必再從數(shù)據(jù)庫服務(wù)器那兒去檢索,只要直接從內(nèi)存中取過來就行了,這樣可以提高應(yīng)用程序的性能。
  不過,如果應(yīng)用程序需要頻繁地更新BLOB字段的值,這時(shí)候反而應(yīng)當(dāng)把CacheBlobs屬性設(shè)為False,這樣能保證檢索到的BLOB字段的值總是最新的。
6.9.2 緩存更新
  TBDEDataSet提供了緩存更新的技術(shù)。所謂緩存更新就是,應(yīng)用程序從數(shù)據(jù)庫中檢索數(shù)據(jù),在本地緩存中建立一個(gè)副本,用戶對(duì)數(shù)據(jù)進(jìn)行修改后,也只是反映在緩存中,以后可以調(diào)用ApplyUpdates一次性地把所有的修改反映到數(shù)據(jù)集中。
  可以看出,緩存更新技術(shù)可以明顯地提高應(yīng)用程序的性能,而且可以方便地取消修改,只要還沒有調(diào)用ApplyUpdates。下面列出了TBDEDataSet中有關(guān)緩存更新的屬性、方法和事件:
.CachedUpdates如果這個(gè)屬性設(shè)為True,緩存更新有效;
.UpdateObject用于指定一個(gè)TUpdateSQL構(gòu)件來更新基于查詢的數(shù)據(jù)集;
.UpdatePending如果緩存中有未決的記錄,這個(gè)屬性就返回True;
.UpdateRecordTypes指定數(shù)據(jù)集中哪些記錄是可見的;
.UpdateStatus返回當(dāng)前的更新狀態(tài);
.OnUpdateError如果更新過程中出錯(cuò)將觸發(fā)這個(gè)事件;
.OnUpdateRecord每更新一條記錄就會(huì)觸發(fā)一次這個(gè)事件;
.ApplyUpdates把緩存中的數(shù)據(jù)寫到數(shù)據(jù)集中;
.CancelUpdates把緩存中未決的修改取消;
.CommitUpdates把緩存清掉;l FetchAll從數(shù)據(jù)庫檢索所有記錄到緩存中;
.RevertRecord撤消對(duì)當(dāng)前記錄的修改。
6.10 TDBDataSet
  TDBDataSet是從TBDEDataSet繼承下來的,它提供了數(shù)據(jù)庫和會(huì)話期管理的能力。
  TDBDataSet中增加了若干個(gè)屬性和方法用于管理數(shù)據(jù)庫和BDE會(huì)話期,包括:
.CheckOpen檢查數(shù)據(jù)庫是否已打開;
.Database返回一個(gè)TDatabase構(gòu)件;
.DBHandle返回一個(gè)BDE句柄,調(diào)用BDE的API時(shí)要用到這個(gè)句柄;
.DBLocale返回當(dāng)前的國際語言驅(qū)動(dòng)程序;
.DB
session返回一個(gè)BDE會(huì)話期對(duì)象;
.DatabaseName用于指定要訪問的數(shù)據(jù)庫;
.SessionName用于指定一個(gè)BDE會(huì)話期對(duì)象。
  這里詳細(xì)解釋一下DatabaseName屬性和SessionName屬性。如果應(yīng)用程序要訪問遠(yuǎn)程數(shù)據(jù)庫服務(wù)器如Sybase、Oracle或InterBase,應(yīng)當(dāng)用TDatabase構(gòu)件來連接數(shù)據(jù)庫,此時(shí),應(yīng)當(dāng)設(shè)置DatabaseName屬性指定要連接的數(shù)據(jù)庫,可以設(shè)為TDatabase構(gòu)件的名稱。如果沒有顯式地使用TDatabase構(gòu)件,DatabaseName屬性應(yīng)當(dāng)設(shè)為BDE 別名。對(duì)于Paradox和dBASE表來說,可以設(shè)為表的路徑。
  SessionName屬性用于指定一個(gè)BDE會(huì)話期對(duì)象。如果應(yīng)用程序沒有顯式地使用TSession構(gòu)件,不必設(shè)置這個(gè)屬性。如果應(yīng)用程序顯式地使用了多個(gè)TSession構(gòu)件,應(yīng)當(dāng)設(shè)置SessionName屬性指定其中一個(gè)。
  一般來說,應(yīng)用程序用不到DBHandle、DBLocale和DBSession等屬性,除非要直接調(diào)用BDE的API。這三個(gè)屬性都是只讀的。
  TDBDataSet中還有一個(gè)只讀的Provider屬性,它能夠返回一個(gè)IProvider接口。在多層的Client/Server應(yīng)用程序中,客戶程序需要通過IProvider接口與應(yīng)用服務(wù)器通訊。

上一篇:多層數(shù)據(jù)庫開發(fā)十一:TClientDataSet

下一篇:多層數(shù)據(jù)庫開發(fā)五:連接數(shù)據(jù)庫

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點(diǎn)

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 荥经县| 鹤岗市| 尼勒克县| 清涧县| 临江市| 安乡县| 前郭尔| 定州市| 桂林市| 海城市| 吉木乃县| 武陟县| 虎林市| 安宁市| 伊金霍洛旗| 松原市| 安义县| 策勒县| 邳州市| 四平市| 桦南县| 新乡县| 运城市| 台南市| 泽库县| 祁连县| 大英县| 封开县| 营山县| 通辽市| 营山县| 泰州市| 东莞市| 莫力| 响水县| 鹿邑县| 青浦区| 高清| 新平| 金堂县| 万州区|