亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? core6.htm

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

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲黄色录像片| 国产99久久久国产精品| 亚洲欧美中日韩| 国产欧美视频一区二区三区| 久久久综合视频| 久久免费美女视频| 紧缚奴在线一区二区三区| 视频一区二区三区中文字幕| 热久久国产精品| 秋霞午夜av一区二区三区| 青青草国产成人99久久| 久久国产精品区| 黑人巨大精品欧美一区| 国产精品99久久久久久似苏梦涵| 国产福利一区二区三区视频在线 | 99久久夜色精品国产网站| 不卡高清视频专区| 色婷婷亚洲综合| 欧美日韩精品欧美日韩精品一综合| 精品视频色一区| 欧美一区二区久久| 极品瑜伽女神91| 国产一区二区不卡| 成人黄色电影在线| 色婷婷国产精品久久包臀| 欧美军同video69gay| 日韩欧美中文字幕公布| 国产欧美一区视频| 亚洲色图.com| 日韩av在线播放中文字幕| 国产精品资源在线| 91一区二区在线| 欧美一区二区三区的| 国产亚洲一区二区三区四区 | 精品夜夜嗨av一区二区三区| 国产精品一区二区在线播放| 91亚洲男人天堂| 在线不卡一区二区| 国产无人区一区二区三区| 亚洲天堂精品在线观看| 蜜臀av性久久久久蜜臀av麻豆| 国产一区二区女| 在线观看免费视频综合| 久久亚洲精品小早川怜子| 亚洲天堂av老司机| 久久成人久久鬼色| 91蜜桃在线观看| 精品久久国产老人久久综合| 亚洲柠檬福利资源导航| 麻豆久久久久久| 在线观看亚洲一区| 精品一区二区免费| 色悠悠久久综合| 久久久蜜臀国产一区二区| 亚洲午夜精品一区二区三区他趣| 国产尤物一区二区在线| 欧美中文一区二区三区| 日本一区二区免费在线观看视频| 亚洲观看高清完整版在线观看 | 6080国产精品一区二区| 国产精品水嫩水嫩| 蜜臀av国产精品久久久久| 99热在这里有精品免费| 精品国产成人系列| 亚洲国产裸拍裸体视频在线观看乱了| 国产精品中文字幕欧美| 欧美一三区三区四区免费在线看| 成人高清视频在线观看| 欧美一区二区三区四区在线观看| 综合电影一区二区三区 | 欧美一区二区三区免费大片| 一区二区视频在线| 国产v日产∨综合v精品视频| 日韩一区二区免费视频| 亚洲国产精品久久不卡毛片| 99久久精品国产导航| 国产喂奶挤奶一区二区三区| 久久精品国产精品青草| 欧美日韩高清影院| 亚洲九九爱视频| www.在线欧美| 中文字幕第一页久久| 国产在线视频一区二区| 日韩午夜精品电影| 精品视频在线视频| 亚洲精品久久久蜜桃| 成人av在线资源| 国产日韩欧美制服另类| 国产一区二区三区最好精华液| 欧美一区二区性放荡片| 午夜精品福利视频网站| 欧美色综合网站| 亚洲图片欧美色图| 欧美丝袜丝交足nylons图片| 亚洲另类一区二区| 欧美亚洲国产一区二区三区| 亚洲精品高清在线| 色婷婷综合久久| 亚洲一区二区在线播放相泽| 欧美影院一区二区| 亚洲亚洲精品在线观看| 欧美午夜电影在线播放| 亚洲成人黄色影院| 亚洲精品免费播放| 欧洲av在线精品| 五月天欧美精品| 日韩欧美国产综合| 国精品**一区二区三区在线蜜桃| 精品国产第一区二区三区观看体验| 精品午夜久久福利影院| 久久久久久久综合日本| 丁香另类激情小说| 亚洲视频免费看| 色乱码一区二区三区88| 亚洲五月六月丁香激情| 4438x亚洲最大成人网| 麻豆久久久久久久| 国产欧美中文在线| 91看片淫黄大片一级| 亚洲午夜精品在线| 欧美一区二区三区播放老司机| 美女视频第一区二区三区免费观看网站| 一区二区激情视频| 欧美日韩激情一区二区| 麻豆精品久久精品色综合| 久久精品人人爽人人爽| 99久久精品国产导航| 亚洲成精国产精品女| 精品久久一区二区三区| 成人高清av在线| 亚洲一线二线三线久久久| 日韩一区二区三区av| 国产成人在线观看免费网站| 亚洲天天做日日做天天谢日日欢| 在线观看国产日韩| 蜜桃精品视频在线观看| 国产精品免费久久| 欧美日韩色综合| 国产一区二区电影| 亚洲一区在线视频| 欧美精品一区二区三区在线| jlzzjlzz国产精品久久| 成人午夜免费电影| 亚洲一区二区在线免费看| 2021国产精品久久精品| 91丨porny丨户外露出| 青青青爽久久午夜综合久久午夜 | 日韩va亚洲va欧美va久久| 欧美激情一区二区三区蜜桃视频| 欧洲生活片亚洲生活在线观看| 免费在线观看一区| ...av二区三区久久精品| 欧美日韩电影一区| 国产69精品久久久久毛片| 91精品国产乱码| 亚洲欧美自拍偷拍色图| 欧美一区二区三区在线观看视频| 国产91精品一区二区麻豆网站| 亚洲制服丝袜av| 国产女人18毛片水真多成人如厕| 亚洲免费观看高清完整版在线观看| 欧美精选一区二区| 99免费精品视频| 久热成人在线视频| 亚洲综合在线电影| 国产日产欧美精品一区二区三区| 欧美日韩在线播放一区| 成人免费看视频| 六月丁香婷婷久久| 亚洲一区二区三区视频在线播放| 国产日产欧美一区| 日韩精品一区二区在线| 日本韩国一区二区三区| 国产成人av在线影院| 青青草国产精品97视觉盛宴| 一区二区激情视频| 国产精品福利一区| 久久伊人中文字幕| 欧美日韩国产高清一区| 色综合久久天天| 丁香另类激情小说| 国产在线一区二区综合免费视频| 欧美日韩国产中文| 91啪亚洲精品| 成人污视频在线观看| 国产尤物一区二区在线| 麻豆精品一二三| 青青草97国产精品免费观看| 亚洲国产成人va在线观看天堂| 亚洲日本va午夜在线影院| 国产日韩成人精品| 久久免费视频一区| 久久综合999| 欧美成人a在线| 7777女厕盗摄久久久| 欧美日韩一区二区三区四区| 色婷婷精品大在线视频 | 国产欧美日韩不卡免费| 精品国产制服丝袜高跟| 日韩精品一区二区三区在线|