第13章-BDE數(shù)據(jù)庫應用程序開發(fā)ppt課件(全)_第1頁
第13章-BDE數(shù)據(jù)庫應用程序開發(fā)ppt課件(全)_第2頁
第13章-BDE數(shù)據(jù)庫應用程序開發(fā)ppt課件(全)_第3頁
第13章-BDE數(shù)據(jù)庫應用程序開發(fā)ppt課件(全)_第4頁
第13章-BDE數(shù)據(jù)庫應用程序開發(fā)ppt課件(全)_第5頁
已閱讀5頁,還剩146頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、第13章 BDE數(shù)據(jù)庫應用程序開發(fā)13.1 TTable組件13.1.1 TTable組件的常用屬性13.1.2 TTable組件的常用方法13.1.3 TTable組件的常用事件13.2 數(shù)據(jù)源TDataSource組件13.2.1 DataSource組件的常用屬性13.2.2 DataSource組件的事件13.3 數(shù)據(jù)控制類組件13.3.1 數(shù)據(jù)控制類組件的共同特性13.3.2 常用數(shù)據(jù)控制類組件功能簡介13.4 Query組件13.4.1 Query組件的常用屬性13.4.2 Query組件的常用方法13.4.3 靜態(tài)查詢使用字符連接號“+”實現(xiàn)動態(tài)查詢目錄使用Params屬性實現(xiàn)參

2、數(shù)查詢使用ParamByName方法實現(xiàn)動態(tài)查詢13.5 使用BDE開發(fā)數(shù)據(jù)庫應用程序13.5.1 創(chuàng)建數(shù)據(jù)庫表13.5.2 制作應用程序界面13.5.3 編寫代碼13.6 小結(jié)13.7 習題目錄 Dephi具備強大的數(shù)據(jù)庫應用開發(fā)能力,支持多種數(shù)據(jù)庫訪問機制。其中一種就是基于BDE的數(shù)據(jù)庫應用開發(fā)。BDE(Borland DataBase Engine)是Borland公司為其開發(fā)工具研發(fā)的一種可以被多個應用程序共享的數(shù)據(jù)訪問機制。它封裝了強大的數(shù)據(jù)庫操作API,可以對本地數(shù)據(jù)庫或遠程數(shù)據(jù)庫輕松實現(xiàn)諸如創(chuàng)建、修改數(shù)據(jù)庫結(jié)構(gòu)、數(shù)據(jù)存取、更新等操作。通過數(shù)據(jù)庫驅(qū)動與數(shù)據(jù)庫進行連接,使BDE能為多

3、種類型的數(shù)據(jù)庫服務器提供統(tǒng)一的訪問接口。根據(jù)Delphi版本不同,可以訪問Paradox、 dBASE、 FoxPro、 Access等類型的本地數(shù)據(jù)庫,同時通過ODBC來訪問所擁有的可用ODBC數(shù)據(jù)源。明顯地,在發(fā)布基于BDE的數(shù)據(jù)庫應用程序的時候,必須包含一份BDE的拷貝。這樣會增加應用程序的體積和程序布署的復雜程度。盡管在應用程序中可以直接通過BDE的API進行數(shù)據(jù)庫操作,但Delphi在組件面板的BDE頁上提供的組件封裝了其中大部分的功能,使用它們無疑可以使開發(fā)工作變得更加簡單、高效。利用BDE開發(fā)數(shù)據(jù)庫應用程序一般涉及到三類組件:BDE組件、Data Access組件和Data Co

4、ntrols組件。這些組件的關(guān)系如圖13-1所示。圖13-1 利用BED組件訪問數(shù)據(jù)庫這三類組件分別分布在Delphi2005的Tool Palettek的BDE頁、Data Access頁和Data Controls頁,如圖13-2、13-3、13-4。圖13-2 BDE組件圖13-3 數(shù)據(jù)訪問組件圖13-4數(shù)據(jù)控制組件13.1 TTable組件 TTable組件通過BDE直接訪問數(shù)據(jù)庫表中的每一條記錄和所有字段。它是最重要的數(shù)據(jù)集部件之一,使用頻率非常高。這里主要介紹其主要的屬性、方法和事件,更詳細的內(nèi)容請查閱Delphi的聯(lián)機幫助文檔或相關(guān)資料。13.1.1 TTable組件的常用屬性1

5、DatabaseName屬性該屬性指定Table組件要訪問的數(shù)據(jù)庫的名字??梢允且粋€BDE Administrator中定義的數(shù)據(jù)庫別名、一個數(shù)據(jù)庫文件的磁盤路徑或者是一個由TDataBase部件連接的數(shù)據(jù)庫。通常使用的是數(shù)據(jù)庫別名,好處是應用程序不用關(guān)心數(shù)據(jù)庫文件實際存儲的位置。如果數(shù)據(jù)庫文件的存儲位置發(fā)生改變,只需要在BDE Administrator中修改別名指向的路徑信息即可。2TabelName屬性該屬性指定Table組件要訪問數(shù)據(jù)庫中具體的數(shù)據(jù)表名稱。它可以是一個數(shù)據(jù)表名,也可以是數(shù)據(jù)表文件的文件名(包括完整的路徑)。同理,通常應該使用數(shù)據(jù)表的名稱。如果在設計期先設置DateBas

6、eName屬性,指定數(shù)據(jù)庫別名,然后就可以通過對象監(jiān)視器在數(shù)據(jù)表名的下拉列表中選擇要訪問的數(shù)據(jù)表。需要注意的是,修改這兩個屬性,數(shù)據(jù)集都必須處于關(guān)閉狀態(tài),即Active屬性為False。3TableType屬性該屬性指定與TTable部件相連接的數(shù)據(jù)庫表的類型。其可能的取值及意義如表13-1: 表 13-1 數(shù)據(jù)庫表類型取值及意義 如果TableType屬性取值為ttDefault時,表示數(shù)據(jù)庫表的類型由數(shù)據(jù)庫文件的擴展名決定。具體情況為:如果數(shù)據(jù)庫文件的擴展名為.DB或沒有擴展名,表的類型是Paradox表;如果數(shù)據(jù)庫文件的擴展名為.DBF時,表的類型是dBASE表;如果數(shù)據(jù)庫文件的擴展名為

7、.TXT時,表的類型是文本數(shù)據(jù)庫表。 注意,該屬性不適用于連接遠程SQL數(shù)據(jù)庫服務器中表的時候。4Active屬性該屬性為Boolean類型,通過該屬性可以判斷或指定是否打開數(shù)據(jù)集。如果該屬性為False,表 示數(shù)據(jù)庫被關(guān)閉,此時數(shù)據(jù)集不能存取數(shù)據(jù),而數(shù)據(jù)感知組件也不能進行數(shù)據(jù)讀取和郵寄修改結(jié)果的操作。當將該屬性值設置為True時,將執(zhí)行下列操作:觸發(fā)BeforeOpen事件將數(shù)據(jù)集設為dsBrowse(瀏覽)狀態(tài)制定數(shù)據(jù)訪問方法(通常是建立游標)觸發(fā)AfterOpen事件當將該屬性值設置為False時,將執(zhí)行下列操作:觸發(fā)BeforeClose事件把State屬性設置為dsInactive(

8、關(guān)閉)狀態(tài)關(guān)閉游標觸發(fā)AfterClose事件設計期可以在對象監(jiān)視器里修改該屬性值,運行時則可以通過給屬性賦值或調(diào)用相應方法實現(xiàn)該屬性值的修改,例如:語句: Table1.active:=true; 等價于 Table1.open; Table1.active:=false 等價于 Table1.close;5Exclusive屬性 該屬性是Boolean,用來指定是否以共享方式打開數(shù)據(jù)庫表。如果值為True,當打開一個數(shù)據(jù)庫表時,其他用戶就不能訪問該表了,如果表已經(jīng)被期它用戶使用,則會產(chǎn)生一個異常;若Exclusive的值為False,將以共享方式打開一個數(shù)據(jù)庫表。 顯然不能將其他用戶正在訪

9、問的表以互斥方式打開(設定Exclusive的值為True)。對于SQL數(shù)據(jù)庫服務器上的數(shù)據(jù)庫表,當以互斥方式被一個用戶打開時,其他用戶可以讀取該表中的數(shù)據(jù),但不能修改表中的數(shù)據(jù),當然有些數(shù)據(jù)庫 服務器不支持這種方式,這要具體參看有關(guān)的數(shù)據(jù)庫服務器的文檔。在改變該屬性值前,數(shù)據(jù)集必需先關(guān)閉。在設計期,如果已經(jīng)設置Active屬性為True,就不要把該屬性也設置為True。因為IDE已經(jīng)打開了指定的表,這樣的話會產(chǎn)生一個異常。6ReadOnly屬性該屬性決定用戶是否能夠?qū)Ρ碇械臄?shù)據(jù)進行讀寫。值為True 時,用戶只能讀取表中的數(shù)據(jù),值為False時,用戶可以讀寫表中的數(shù)據(jù)(前提是用戶有讀寫數(shù)據(jù)庫

10、表的權(quán)限)。7CanModify屬性該屬性是一個只讀屬性,用戶不能夠修改其屬性值,它由應用程序打開一張表時自動設置,反映用戶對數(shù)據(jù)庫表擁有的實際特權(quán)。當ReadOnly屬性值為True時,該屬性將自動地被設為False,當ReadOnly屬性值為False時,若用戶對數(shù)據(jù)庫表有讀寫權(quán)限時,該屬性值為True,否則該屬性值為False。當該屬性值為False時,數(shù)據(jù)庫表是只讀的,不能將數(shù)據(jù)集置為編輯或插入狀態(tài);當該屬性為True時,雖然數(shù)據(jù)庫表對應的數(shù)據(jù)集部件可以置成編輯和插入狀態(tài),但是用戶不一定能夠更新表中的數(shù)據(jù),因為這還要受到其他因素的限制,如用戶對數(shù)據(jù)庫服務器的訪問權(quán)限等。8IndexFi

11、elds屬性IndexFields的屬性值是一個下標從0開始的數(shù)據(jù)庫表中字段名的數(shù)組,它包含與TTable組件相連的數(shù)據(jù)庫表中的全部索引字段。IndexFieldsCount屬性說明表中索引字段的個數(shù)。這兩個屬性值都是只讀的,只有在程序運行過程中可用。運行期應該使用IndexFieldsName屬性來對數(shù)據(jù)集進行排序,而不要直接設置IndexFields屬性的值。9IndexName屬性和IndexFieldNames屬性IndexName該屬性是一個只讀的輔助索引名列表,存放建立數(shù)據(jù)庫表時定義的所有輔助索引名。IndexFieldNames屬性指定數(shù)據(jù)庫表用來排序的索引字段名,多個字段名之間

12、用分號隔開。字段必須存在于相應的數(shù)據(jù)庫表中,否則會導致錯誤。這兩個屬性是互斥的,設置其中一個,會自動清除另一個。10. KeyExclusive屬性該屬性是布爾型變量,默認值為False。它的作用是在表中指定檢索范圍時,用來指定是否包括滿足過濾條件的邊界記錄。當值為False時,檢索范圍包括邊界記錄,否則不包括邊界記錄。11State屬性 該屬性標明數(shù)據(jù)集所處的工作模式,即確定可 以對數(shù)據(jù)做哪些操作。其可能的取值及意義如表13-2: 表 13-2 數(shù)據(jù)表工作模式取值及意義 數(shù)據(jù)集的狀態(tài)在應用程序處理數(shù)據(jù)的過程中不斷的變化著。當數(shù)據(jù)集被打開時,狀態(tài)由dsInactive改為dsBrowse。程序

13、可以調(diào)用Edit、Insert方法將數(shù)據(jù)集置為dsEdit、dsInsert狀態(tài)。如果是TTable或TClientDataSet部件,還可以調(diào)用SetKey方法或SetRange方法將數(shù)據(jù)集置為dsSetKey狀態(tài)。郵寄或撤消地數(shù)據(jù)的修改將把數(shù)據(jù)集由當前狀態(tài)置為dsBrowse狀態(tài)。關(guān)閉數(shù)據(jù)集則將數(shù)據(jù)集由當前狀態(tài)置為dsInactive狀態(tài)。12.Filter屬性和 Filtered屬性在訪問一個數(shù)據(jù)集時,當只需要瀏覽符合特定條件的記錄而不是全部記錄時,可以通過設置數(shù)據(jù) 集組件的Filter屬性很方便的實現(xiàn)。Filter屬性可以用一個字符串描述為數(shù)據(jù)集設定的過濾條件。程序運行時,所訪問的數(shù)據(jù)

14、集中,只有符合該過濾條件的記錄才會返回給數(shù)據(jù)集組件。比如,如下的過濾屬性設置使數(shù)據(jù)集只返回state字段是CA或MA的記錄:State = CA or State = MA;過濾條件的設置支持通配符,比如:State = M*表示以“M”開頭的所有取值。如果用來設置過濾條件的字段名中有空格,則需要用一對“ ”符號將該字段名括直來,比如:Species Name = Gymnothorax mordax。過濾屬性的設置可以有多種方式,例如:Dataset1.Filter := State = + QuotedStr(CA);/固定字符串方式;Dataset1.Filter := Edit1.Te

15、xt; /由用戶輸入;Dataset1.Filter := State = + QuotedStr(Edit1.Text);/部分由用戶輸入;Dataset1.Filter := State CA or State = BLANK;/復雜條件表達式;在條件表達式中可使用的操作符有如下幾個:、=、=、=、AND、NOT、OR、+、-、*、/、*(通配符)Filtered屬性為Boolean,用來指定Filter屬性設置的過濾條件是否有效。因此,在設置完Filter屬性后,還必須設置Filtered屬性為True,才能真正的實現(xiàn)對記錄的過濾。13.Bof屬性和Eof屬性這兩個屬性都是Boolean

16、類型,分別用來測試記錄指針(即當前記錄)是否處于表的開頭(第一條記錄)和結(jié)尾(最后一條記錄),如果是,則返回True。Bof(Beginning of file)屬性在下列情況下返回True,其它情況下均返回False: 打開數(shù)據(jù)集。 調(diào)用數(shù)據(jù)集組件的First方法。 記錄指針指向第一條記錄時調(diào)用數(shù)據(jù)集組件的Prior方法。 對一個空數(shù)據(jù)集或數(shù)據(jù)集使用范圍調(diào)用SetRange方法。 相應的,Eof(end-of-file)屬性在下列情況下返回True,其它情況下返回False: 打開空數(shù)據(jù)集。 調(diào)用數(shù)據(jù)集組件的Last方法。 記錄指針指向最后一條記錄時調(diào)用數(shù)據(jù)集組件的Next方法。 對一個空數(shù)

17、據(jù)集或數(shù)據(jù)集使用范圍調(diào)用SetRange方法。 明顯地,如果Bof和Eof屬性都返回True,則該數(shù)據(jù)集或使用范圍為空。14.RecordCount屬性。 該屬性為LongInt類型,用于返回數(shù)據(jù)集總的記錄條數(shù)。利用它和RecNo屬性配合,可以代替First、Last、MoveBy、Prior等方法實現(xiàn)對數(shù)據(jù)集所有記錄的遍歷操作。但是在程序中應該謹慎使用該屬性,因為該操作代價很大,影響程序性能,特別是在SQL查詢結(jié)果返回大量記錄的時候。因此通常只對Paradox和dBASE表使用該屬性。 另外,如果數(shù)據(jù)集不是Paradox類型并且有過濾條件在起作用或者是 設置了使用范圍,則該屬性返回值可能僅是

18、一個近似值。15.FieldValues屬性 在程序中,可以通過FieldValues屬性訪問數(shù)據(jù)集當前記錄的各個字段值。該屬性的定義如下:property FieldValuesconst FieldName: string: Variant; default;其中的FieldName是要訪問的字段名。該參數(shù)可以是單個字段名,也可以是多個字段名或字段對象的集合。因為這種靈活性,通常在程序,采用該屬性或FieldByName方法比采用Fields、Fieldist等屬性訪問字段值要更好一些。另外,該屬性為了能處理各種數(shù)據(jù)類型的字段使用的是可變類型值,這樣在處理速度上會比使用字段原本的數(shù)據(jù)類型值

19、要慢(比如使用字段對象的as*屬性),特別是有大量數(shù)據(jù)需要處理時更是如此。該屬性使用示例如下,代碼功能是向數(shù)據(jù)集中添加一條記錄:SampleTable.Append; SampleTable.FieldValuesALPHANUMERIC := Edit1.text;SampleTable.FieldValuesINTEGER := StrToInt(Edit2.text);SampleTable.Post; TTable部件中MasterSource屬性和MasterFields屬性是用于定義主-從關(guān)系表的。MasterSource屬性指定主表對應的TDataSource部件,MasterF

20、ields屬性指定主表和明細表之間建立聯(lián)系的字段。主表和明細表建立一對多關(guān)系時,如果是多個字段要用分號隔開。在設計階段可以使用字段連接設計器(Field Link Designer)為兩上表創(chuàng)建一對多的關(guān)系。13.1.2 TTable組件的常用方法1.設定數(shù)據(jù)庫表的使用范圍 應用程序可能只需對表中一部分記錄進行操作,此時應為應用程序指定一個使用表中記錄的范圍。為此,TTable組件提供了下列方法供用戶使用: SetRangeStart和EditRangeStart方法 SetRangeEnd和EditRangeEnd方法 SetRange(Start Values,End Values)方法

21、ApplyRange方法 CancelRange方法 1)SetRangeStart方法用于指定檢索范圍的起始記錄,調(diào)用SetRangeStart方法之后,可以為起始記錄的一個或多個字段指定相應的字段值。SetRangeEnd方法用于指定檢索范圍的結(jié)束記錄,調(diào)用SetRangeEnd方法之后,可以為結(jié)束記錄的一個或多個字段指定相應的字段值。 2)SetRange方法包含了SetRangeStart和SetRangeEnd方法的功能,它可以同時指定檢索范圍的起始和結(jié)束記錄,起始記錄和結(jié)束記錄的字段值以數(shù)組形式送給SetRange,其基本形式是:SetRange(起始值,結(jié)束值) 3)ApplyR

22、ange方法根據(jù)SetRangeStart,SetRangeEnd或SetRange方法說明的檢索范圍的起始和結(jié)束記錄,具體設定一個檢索范圍,調(diào)用ApplyRange方法之后, 應用程序只能對檢索范圍內(nèi)的記錄進行有關(guān)的操作。 4)CancelRange方法的作用與ApplyRange方法的作用是相反的,這是取消為表設定的檢索范圍,調(diào)用CancelRange方法之后應用程序可以對表中全部記錄進行有關(guān)的操作。注意:如果是paradox表或dBASE表,調(diào)用SetRangeStart,SetRangeEnd、SetRange時,只能為表中的索引字段或定義的索引指定相應的字段值,以設定檢索范圍。如果使

23、用SQL數(shù)據(jù)庫服務器中的數(shù)據(jù)庫表,可以為IndexFieldNames屬性中指定的字段指定相應的字段值。 5)EditRangeStart和EditRangeEnd方法是用來設定一個可編輯的范圍,其使用方法完全類似與SetRangeStart和SetRangeEnd。2.數(shù)據(jù)維護方法數(shù)據(jù)集中的數(shù)據(jù)維護主要包括數(shù)據(jù)記錄的修改,插入和刪除。Delphi為數(shù)據(jù)集部件提供了相應的方法用于其中的數(shù)據(jù)維護。這里以TTable組件為例介紹這些方法。1) Edit方法:將數(shù)據(jù)集置為編輯狀態(tài)。如果數(shù)據(jù)集為空,則調(diào)用Insert方法,否則執(zhí)行以下動作: 如果需要,投寄之前的記錄的修改。 檢查CanModify屬性

24、,如果數(shù)據(jù)集不可編輯,則產(chǎn)生一個異常。 調(diào)用BeforeEdit事件處理過程。 檢索記錄。 將數(shù)據(jù)集置為編輯狀態(tài),允許程序或用戶編輯數(shù)據(jù)。 向所關(guān)聯(lián)的組件廣播數(shù)據(jù)集的狀態(tài)改變。 調(diào)用AfterEdit事件處理過程。2) Append方法:向數(shù)據(jù)集的未尾新添加一條空記錄,并將其置為當前記錄。例如:SampleTable.Append;SampleTable.FieldValuesALPHANUMERIC := Edit1.text;SampleTable.FieldValuesINTEGER :=StrToInt(Edit2.text);SampleTable.Post;3) Insert方法:

25、向數(shù)據(jù)集中新添加一條空記錄,并將其置為當前記錄。例如:table1.Insert;table1.FieldByName(QUANTITY).AsInteger :=StrToInt(Edit1.Text);table1.Post;這兩個方法都將數(shù)據(jù)集置為插入狀態(tài),以在表中添加新記錄。Insert方法是在當前指針位置的記錄后面插入一條新記錄,Append方法是在表的最后插入一條新記錄。然而,無論用戶是調(diào)用Insert方法還是Append方法插入新記錄,增加記錄到一個具有索引的表中時,其寫入位置都是按照索引順序的,也就是說對于索引表格Insert方法和Append方法的作用是一樣的。另外,Inse

26、rt方法和Append方法實際上只插入一條空白記錄,所以必須在調(diào)用Insert或Append方法之后,給新記錄的各個字段賦值,最后調(diào)用post方法,將插入的記錄寫回數(shù)據(jù)庫表。 4) Post方法: 將插入的新記錄和修改的記錄寫回磁盤上的數(shù)據(jù)庫表,即投寄。當投寄成功時數(shù)據(jù)集回到瀏覽狀態(tài),若投寄不成功數(shù)據(jù)集仍然保持原有狀態(tài)。post方法既可以顯式地調(diào)用,也可以隱含地調(diào)用。當數(shù)據(jù)集處于編輯狀態(tài)或插入狀態(tài),當移動記錄指針時,Delphi會隱含地調(diào)用post方法,將當前記錄的修改寫回數(shù)據(jù)庫表;在程序調(diào)用Insert方法或Append方法時,也會隱含地調(diào)用Post方法,將先前的數(shù)據(jù)集的修改寫回數(shù)據(jù)庫表。在

27、程序中,Edit方法和post方法常常配合在一起使用,用于修改表中的記錄。5) Cancel方法:取消當前尚未投寄的修改操作且將數(shù)據(jù)集置為瀏覽狀態(tài)。通常用在響應用戶取消修改的請求中,例如:if MessageDlg(Update Record?, mtConfirmation, mbYes, mbNo, 0) = mrYes then table1.Postelse table1.Cancel;6) Delete方法:刪除當前記錄指針所在的記錄,將記錄指針指向一條記錄且將數(shù)據(jù)集置為瀏覽狀態(tài)。如果數(shù)據(jù)集處于非活動狀態(tài),則產(chǎn)生一個異常,否則做以下操作: 驗證數(shù)據(jù)集非空,否則產(chǎn)生一個異常。 如果需要

28、,投寄之前的記錄的修改。 調(diào)用BeforeDelete事件處理過程。 刪除當前記錄,并清除與之有關(guān)的緩沖區(qū)。 將數(shù)據(jù)集置為dsBrowse狀態(tài)。 將下一條未被刪除的記錄設置為當前記錄。如果刪除的是最后一條記錄,則將前一條記設置為當前記錄。 調(diào)用AfterDelete事件處理過程。7) AppendRecord方法:該方法的過程申明:procedure AppendRecord(const Values: array of const);其作用是在表的最后插入一條新記錄,記錄的各個字段值按順序?qū)贏ppendRecor的參數(shù)值。如下例: Customer.AppendRecord(CustNo

29、Edit.Text,CoNameEdit.Text, AddrEdit.Text, Nil, Nil, Nil, Nil, Nil, Nil, DiscountEdit.Text);8) InsertRecord方法:該方法的過程申明:procedure InsertRecord(const Values: array of const);其作用是在當前指針所在記錄的后面插入一條新記錄,記錄的各個字段值按順序?qū)贗nsertRecord的參數(shù)值。例如:Customer.InsertRecord(CustNoEdit.Text, CoNameEdit.Text, AddrEdit.Text,

30、Nil, Nil, Nil, Nil, Nil, Nil, DiscountEdit.Text);AppendRecord方法和InsertRecord方法比Append和Insert方法使用起來更簡單方便一些。 它們直接在表中插入一條新記錄,其參數(shù)按順序作為新記錄各字段值,并且不需顯式地調(diào)用post方法。在用參數(shù)數(shù)據(jù)給新記錄賦字段值時,可以為每一個字段提供一個值,也可以省略某個字段序列后面的一些字段值,Delphi會用空值來填充這些字段。用戶也可以傳遞保留字NIl明確地對某些字段用空值填充。9) SetFields方法:該方法過程申明:procedure SetFields(const Va

31、lues: array of const);其功能是一次修改表中當前記錄的多個字段的值。調(diào)用該方法之前必須將數(shù)據(jù)集部件置成編輯狀態(tài),調(diào)用之后,還要調(diào)用post方法,才能真正將當前記錄的修改寫回數(shù)據(jù)庫表。調(diào)用SetFields方法時,參數(shù)值必須與表中實際的字段對應,并且數(shù)據(jù)類型要匹配。例如: Table1.Edit;Tabel1.SetFields(, , ,9600000,1200000000);Tabel1.post;10) FieldByName方法:方法定義:function FieldByName(const FieldName: string): TField;該方法用來返回由參數(shù)F

32、ieldName指定名稱的字段信息。注意其返回值是一個字段對象(TField類型)。如果指定的字段并不存在,則會引發(fā)一個EDatabaseError異常。該方法的功能與用法與FieldValues屬性很類似。程序示例:Table1.Insert;Table1.FieldByName(QUANTITY).AsInteger := StrToInt(Edit1.Text);Table1.Post;11) Abort方法:該方法是用于取消其他方法的調(diào)用的,如在插入記錄、修改記錄和刪除記錄之前,往往需要用戶確認是否真的要執(zhí)行這種操作,此時調(diào)用Abort方法便可取消各種方法的調(diào)用。下面的代碼是在用戶刪除

33、一條記之前,讓用戶確認是否真的要執(zhí)行刪除操作。Tabel1.BeforeDelete(DataSet:TDataSet);beginIf MessageDlg(真的要刪除記錄嗎?,mtConfirmation,mbyesNoCanel,0) mryes Then Abort; 取消刪除操作end;3.移動記錄指針的方法1) First方法:將記錄指針移到第一條記錄位置處。2) Last方法:將記錄指針移到最后一條記錄位置處。3) Next方法:將記錄指針移到下一條記錄位置處。4) Prior方法:將記錄指針移到上一條記錄位置處。4.數(shù)據(jù)庫表的操作方法1) CreateTable方法:調(diào)用Cre

34、ateTable方法,可以在程序中根據(jù)需要定義并創(chuàng)建新的數(shù)據(jù)庫表。如果指定的表名已經(jīng)存在,則該方法會用新定義的表結(jié)構(gòu)覆蓋原表的結(jié)構(gòu)和數(shù)據(jù),所以在調(diào)用該方法創(chuàng)建一個新表之前,應該檢查Exists屬性確定表是否已存在。如果指定了FieldDefs屬性的值,則其值將被用于新表中的字段定義,否則將用Fields屬性中的值來定義表結(jié)構(gòu)。如果IndexDefs屬性中包含有值,則將被用作定義新表的索引。用該方法定義新表的步驟如下:設置TTable組件Active屬性為False;指定要創(chuàng)建新表的類型和表名檢查該名字的表是否存在定義字段定義索引調(diào)用CreateTable方法程序示例:with Table1 d

35、o begin Active := False; DatabaseName := DBDEMOS; TableType := ttParadox; TableName := CustInfo; if not Table1.Exists then beginwith FieldDefs do begin Clear; with AddFieldDef do begin Name := Field1; DataType := ftInteger; Required := True; end; with AddFieldDef do begin Name := Field2; DataType :=

36、 ftString; Size := 30; end; end;with IndexDefs do begin Clear; with AddIndexDef do begin Name := ; Fields := Field1; Options := ixPrimary; end; with AddIndexDef do begin Name := Fld2Indx; Fields := Field2; Options := ixCaseInsensitive; end; end; CreateTable; end;end;2) DeleteTable方法:該方法用來刪除與TTable組件

37、關(guān)聯(lián)的數(shù)據(jù)庫表。調(diào)用該方法之前必須先關(guān)閉表。刪除操作將清除表中所有數(shù)據(jù)和表的結(jié)構(gòu),使用要慎重。如果僅僅是想清除數(shù)據(jù),可以使用EmptyTable方法。程序示例:with Table1 dobegin Active := False; DatabaseName := DBDEMOS; TableName := Customer; TableType := ttParadox; DeleteTable;end;2) EmptyTable方法:該方法用來清空與TTable組件關(guān)聯(lián)的數(shù)據(jù)庫表。如果用戶對表沒有該操作權(quán)限,清空操作失敗。 3) RenameTable方法:該方法定義:procedure

38、RenameTable(const NewTableName: String);其作用是重命名與TTable組件關(guān)聯(lián)的Paradox或dBASE表。新的表名由參數(shù)NewTableName給出。 4) IsEmpty方法:該方法定義:function IsEmpty: Boolean;其作用是判斷與TTable組件關(guān)聯(lián)的數(shù)據(jù)庫是否是空表。返回值為True表示該表為空表,即不包含任何數(shù)據(jù)記錄。 5) Open方法:該方法用于打開TTable組件關(guān)聯(lián)的數(shù)據(jù)庫表以進行數(shù)據(jù)訪問。6) Close方法:該方法用于打開TTable組件關(guān)聯(lián)的數(shù)據(jù)庫表以進行數(shù)據(jù)訪問。查看Open和Close方法的源代碼會發(fā)現(xiàn),

39、這兩個方法事實上就是通過分別設置TTable組件的Active屬性值為True和False實現(xiàn)的。因此,調(diào)用它們的結(jié)果,在Active屬性中已詳細介紹過,這里不再重復。5.查找數(shù)據(jù)庫表中的記錄 要想在數(shù)據(jù)庫表中查找記錄,必須指定要查找記錄的一些字段的值,然后在表中檢索相匹配的記錄。如果在Paradox或dBASE表中查找記錄,則對應的字段必須是表中的關(guān)鍵字段或輔助索引字段。如果查找SQL服務器中的表,那么查找值 必須是表的IndexFieldNames屬性中指定的字段。Delphi提供了兩種方式在數(shù)據(jù)庫表中查找記錄:Goto方式和Find方式,主要區(qū)別在于指定查找值的方法不同。(1)使用Got

40、o方式查找的方法有SetKey方法、GotoKey方法和GotoNearest方法。其操作步驟如下: 確保要查找的字段是關(guān)鍵字段或輔助索引字段。 調(diào)用SetKey方法把與表對應的TTable部件置成查找狀態(tài)。 把查找值賦給相應的字段。 調(diào)用GotoKey方法,測試它的返回值以判斷查找是否成功。如下例:Table1.SetKey; Table1.Field0.AsString := Edit1.Text; Table1.GotoKey; 調(diào)用GotoKey方法后,如果返回True,則查找成功,同時記錄指針指向找到的記錄;如果返回Fale,則查找失敗,記錄指針的位置不會發(fā)生變化。如下例:Table

41、1.SetKey;Table1.Field0.AsString:= Smith;If not Table1.GotoKey thenShowMessage(記錄沒找到); 如果表中存在多個關(guān)鍵字段或輔助索引字段,但查找時只想為第一個字段指定查找值,則必須要設置TTable組件的KeyFieldCount的屬性值為1。如果想為多個字段指定查找值,只能為相鄰的字段指定查找值,例如輔助索引中共有三個字段,那么我們只能為第一個字段、第一和第二個字段、第一和第二以及第三個字段指定查找值,而不能為第一和第三個字段指定查找值。GotoNearest方法的使用與GotoKey方法完全一樣,只是它用于不精確查找

42、。它不要求查找結(jié)果與查找值精確匹配。如果表中有與查找值精確匹配的記錄時,它將記錄指針移到該記錄處,如果表中沒有與查找值精確匹配的記錄時,它會查找出與查找值最接近的記錄,并將記錄指針移到該記錄處。如果不是以表中的關(guān)鍵字段作為查找字段,也可以為TTable部件的IndexFieldName屬性中的字段或IndexName屬性中的字段指定查找值進行數(shù)據(jù)查找。 例如,假設Customer表中有一個名叫CityIndex的輔助索引,為CityIndex中的字段指定查找值進行查找時,首先設置TTable部件的IndexName屬性為CityIndex,然后再進行查找,下面是具體的程序代碼:Table1.I

43、ndexName := CityIndex;Table1.Open;Table1.SetKey;Table1.FieldByNameCity.AsString := Edit1.Text;Table1.GotoKey; (2)使用Find方式:使用Find方式在數(shù)據(jù)庫中進行數(shù)據(jù)查找的方法有:FindNearest方法和FindKey方法。FindKey方法和FindNearest方法為數(shù)據(jù)查找提供了一個簡單的方法,它們將SetKey、指定查找值、執(zhí)行查找三個步驟融合在一步里完成,它們在指定查找值時,是把各字段的查找值組成一個數(shù)組傳給FindKey或FindNearest。下面是使FindKey

44、方法的一個例子。假設Tabel1對應的表中的第一個字段是關(guān)鍵字段。 Table.FindKey(Edit1.Text); 如果用GotoKey方法完成這一功能則需要編寫下面代碼:Table1.SetKey;Table1.Fields0.AsStrine := Edit.Text;Table1.GotoKey;FindKey方法和FindNearest方法的區(qū)別與GotoKey和GotoNearest方法的區(qū)別是一樣的。6.控制數(shù)據(jù)集組件與數(shù)據(jù)瀏覽組件連接的方法 數(shù)據(jù)集組件具有DisableControls、EnableControls、Refresh三個方法用于控制數(shù)據(jù)集組件和與其相連的數(shù)據(jù)瀏

45、覽組件之間的連接及數(shù)據(jù)的顯示。在用戶修改、更新以及遍歷數(shù)據(jù)庫表中的記錄時,應該調(diào)用DisbaleControls方法切斷數(shù)據(jù)集組件與數(shù)據(jù)瀏覽組件的連接,使數(shù)據(jù)瀏覽組件暫時失效。這樣做的好處是避免每次對數(shù)據(jù)集修改之后,與之相聯(lián)的數(shù)據(jù)瀏覽組件更新其顯示內(nèi)容,一方面降低處理速度,另一方面會產(chǎn)生屏幕閃爍。 EnableControls方法的作用與DisbaleControls方法的作用相反,是用來恢復與數(shù)據(jù)瀏覽部件的連接,使暫時失效的數(shù)據(jù)瀏覽部件正常顯示數(shù)據(jù)集中的記錄信息。 Refresh方法用于刷新數(shù)據(jù)瀏覽部件中的顯示。在調(diào)用Refresh方法時,必須要保證數(shù)據(jù)集組件是打開的。當數(shù)據(jù)集中的記錄被修改

46、之后,調(diào)用Refresh方法,數(shù)據(jù)瀏覽部件中顯示的信息也隨之改變。13.1.3 TTable組件的常用事件 數(shù)據(jù)集組件具有很多的事件。為這些事件編寫處理過程可以進行有效性驗證、計算可計算字段的值、確認對數(shù)據(jù)庫表的多種操作等等。具體事件及其描述如下:BeforeOpen , Afteropen 在數(shù)據(jù)集部件被打開之前/之后被觸發(fā)BeforeClose , Afterclose 在數(shù)據(jù)集部件被關(guān)閉之前/之后被觸發(fā)BeforeInsert , AfterInsert 在數(shù)據(jù)集部件進入插入狀態(tài)之前/之后被觸發(fā)BeforeEdit , AfterEdit 在數(shù)據(jù)集部件被編輯之前/之后被觸發(fā)BeforeP

47、ost , AfterPost 在數(shù)據(jù)集部件投寄被修改的記錄之前/之后被觸發(fā)BeforeCancel , AfterCancel 在數(shù)據(jù)集部件取消前一步操作之前/之后被觸發(fā)BeforeDelete , AfterDelete 在數(shù)據(jù)集部件刪除當前記錄之前/之后被觸發(fā)OnNewRecord 當建立一條新記錄時被觸發(fā)OnCalcFields 當為表中的計算字段計算字段值時被觸發(fā)13.2 數(shù)據(jù)源TDataSource組件 TDataSource部件是數(shù)據(jù)庫應用程序開發(fā)中非常重要的部件,它是連接數(shù)據(jù)集部件和數(shù)據(jù)控制部件的橋梁,使得數(shù)據(jù)集部件中的數(shù)據(jù)能夠在數(shù)據(jù)控制部件中被顯示和操作,同樣數(shù)據(jù)控制部件也需

48、要關(guān)聯(lián)數(shù)據(jù)集部件以獲取和處理數(shù)據(jù)。另外,TDataSource部件也被用來連接兩個數(shù)據(jù)集部件以建立它們之間的主從關(guān)系。它的使用十分簡單,屬性、事件和方法比較少。13.2.1 DataSource組件的常用屬性1DateSet屬性 該屬性說明TDataSource部件從中獲取數(shù)據(jù)的數(shù)據(jù)集部件的名字,可以在設計期或運行期更改該屬性指向不同的數(shù)據(jù)集部件。如果在運行時更改其指向的數(shù)據(jù)集部件,則可以實現(xiàn)用同一個數(shù)據(jù)控制部件顯示或編輯不同數(shù)據(jù)集中的數(shù)據(jù)。2Enable屬性 該屬性是Boolean類型,可以暫時切斷TDataSource部件和與之相連的數(shù)據(jù)集部件的連接。當它的值為False時,該連接被切斷,

49、所有與TDataSource部件相連的數(shù)據(jù)控制部件將變?yōu)橐黄瞻?,不顯示任何數(shù)據(jù)信息。當其值變?yōu)門rue時(默認情況),該連接恢復,與之相連的數(shù)據(jù)控制部件恢復顯示數(shù)據(jù)。但是,實現(xiàn)這種功能更好的方法是調(diào)用數(shù)據(jù)集部件的DisableControls方法和EnableControls 方法,因為這樣可以更方便地控制與數(shù)據(jù)集部件相連的所有TDataSource部件和數(shù)據(jù)控制部件。3AutoEdit屬性該屬性為Boolean類型,默認值為True。用于說明是否將與TDataSource部件相連的數(shù)據(jù)集自動設置為編輯狀態(tài)。若值為True,當用戶試圖修改數(shù)據(jù)控制部件中顯示的數(shù)據(jù)時,TDataSource自動

50、調(diào)用數(shù)據(jù)集的Edit方法將數(shù)據(jù)集設置為編輯狀態(tài),數(shù)據(jù)集部件中的記錄也隨之改變;若值為False,用戶要想通過數(shù)據(jù)控制部件或程序修改數(shù)據(jù)集中的記錄,必須調(diào)用數(shù)據(jù)集部件的Edit方法,將其置為編輯狀態(tài)之后才能夠進行。將該屬性值設置為False,可以保護數(shù)據(jù)不被無意的改動。4State屬性該屬性表明與TDataSource部件關(guān)聯(lián)的數(shù)據(jù)集當前的狀態(tài)。詳細內(nèi)容請參看表13-2。13.2.2 DataSource組件的事件TDataSource部件具有三個事件: OnDataChange事件 OnStateChange OnUpdataData OnDataChange事件:當與TDataSource相

51、連的數(shù)據(jù)集中的記錄指針的位置發(fā)生改變時,該事件就被觸發(fā),也就是說當程序調(diào)用數(shù)據(jù)集部件的Next、Previous、Insert、Append等方法導致記錄指針的位置發(fā)生改變時,便會觸發(fā)該事件。該事件一般用于保持應用中多個部件之間的同步。OnUpdataData事件:當數(shù)據(jù)集部件中當前記錄將要被修改時,觸發(fā)該事件。例如在程序調(diào)用post方法之后但在修改后的數(shù)據(jù)記錄真正被寫回磁盤中的數(shù)據(jù)庫文件之前觸發(fā)該事件,在應用中使用非數(shù)據(jù)瀏覽部件時要它與數(shù)據(jù)集保持同步時常使用該事件進行相關(guān)的處理。 OnStateChange事件:當與TDataSource部件相連的數(shù)據(jù)集部件的狀態(tài)發(fā)生改變時, 便觸發(fā)該事件。

52、因為數(shù)據(jù)集部件的State屬性標明了數(shù)據(jù)集部件當前所處的狀態(tài),當數(shù)據(jù)集的狀態(tài)發(fā)生變 化時,使用該事件進行有關(guān)的處理是很有用的,在一個具體的應用中, 數(shù)據(jù)集部件的狀態(tài)常常是頻繁地變化的,為了跟蹤數(shù)據(jù)集部件的狀態(tài)變化, 可以用下面例子中的程序代碼將數(shù)據(jù)集部件當前的狀態(tài)顯示在一個標簽上:TForm1.DataSource1OnStateChange(Sender : Tobject);Var S : String;beginCase Table1,State of dsInactive : S := Inactive;dsBrowse : S := Browse;dsEdit : S := Edit

53、;dsInsert : S := SetKey;dsSetKey : S := SetKey;end;Label1.Caption := S;end;類似地我們也可以通過檢測數(shù)據(jù)集部件的狀態(tài)來控制有關(guān)的按鈕和菜單項是否有效。 例如:在一個應用窗體中有一個InsertBtn按鈕,用于控制向 數(shù)據(jù)集部件table1對應的數(shù)據(jù)庫表中插入記錄;還有一個CancelBtn按鈕用于控制是否取消用戶對當前記錄的修改或插入新記錄。下面的程序代碼根據(jù)Table1的狀態(tài)來控制這兩個按鈕的功能。Form1.DataSource1OnStateChange(Sender : Tobject);beginInsertB

54、tn.Enabled := (Table1.State = dsBrowse);CancelBtn.Enabled := Table1.State in dsInsert,dsEdit,dsSetKeyend; 上面的代碼中,當Table1處于瀏覽狀態(tài)(Browse狀態(tài)時), 用戶是不能夠向數(shù)據(jù)庫表中插入新記錄的,此時InsertBtn按鈕將變灰暗即無效。當Table1不處于Browse狀態(tài)時,InsertBtn按鈕有效,用戶是可以向表中插入新記錄。同理,只有當Table1處于特入狀態(tài)(Insert狀態(tài))或編輯狀態(tài)(Edit狀態(tài))或查找狀態(tài)(SetKey狀態(tài))時,CancelBtn按鈕才有效,

55、也即用戶可以取消當前插入的記錄、修改當前的記錄以及查找到的結(jié)果等。13.3 數(shù)據(jù)控制類組件Delphi2005在Tool Palette的Data Controls頁上提供了一個數(shù)據(jù)控制部件集合。這些部件主要用于設計對數(shù)據(jù)庫中的數(shù)據(jù)進行瀏覽、編輯、插入、刪除等操作的用戶界面。因而數(shù)據(jù)控制部件常常又被稱為數(shù)據(jù)瀏覽部件。它們其實是在Standard頁上的相應標準部件的基礎上,增加了數(shù)據(jù)瀏覽功能,能夠顯示和編輯數(shù)據(jù)信息。 數(shù)據(jù)控制部件既能夠把數(shù)據(jù)庫中的數(shù)據(jù)顯示到窗體中,又可以將其自身的經(jīng)過修改的數(shù)據(jù)寫回到數(shù)據(jù)庫中。13.3.1 數(shù)據(jù)控制類組件的共同特性大部分數(shù)據(jù)控制類組件的使用方法都很類似,主要包括

56、以下內(nèi)容:建立與數(shù)據(jù)集部件的關(guān)聯(lián)數(shù)據(jù)控制組件必須通過數(shù)據(jù)源組件(TDataSource組件)建立起與數(shù)據(jù)集組件的關(guān)聯(lián)以從中獲取顯示的數(shù)據(jù)。具體做法: 在窗體或數(shù)據(jù)模塊上添加一個數(shù)據(jù)集組件和一個數(shù)據(jù)源組件,分別設置其相關(guān)屬性,使數(shù)據(jù)源組件的DataSet屬性指向數(shù)據(jù)集組件。 向窗體添加數(shù)據(jù)控制類組件,設置其DataSource屬性指向上一步添加的數(shù)據(jù)源組件。 設置其DataField屬性指向數(shù)據(jù)中要顯示的字段名。(由于TDBGrid, TDBCtrlGrid和TDBNavigator組件訪問的是整個數(shù)據(jù)集的所有有效字段,所以沒有DataField屬性,也不需要這一步的操作。) 設置數(shù)據(jù)集組件的A

57、ctive屬性為True,打開數(shù)據(jù)集,顯示數(shù)據(jù)。 編輯或更新數(shù)據(jù) 要通過數(shù)據(jù)控制組件編輯或更新數(shù)據(jù),要求與之相關(guān)聯(lián)的數(shù)據(jù)集必須處于dsEdit狀態(tài)。如果數(shù)據(jù)源組件的AutoEdit屬性為True,則當用戶嘗試在數(shù)據(jù)控制組件中編輯數(shù)據(jù)時,數(shù)據(jù)集組件會自動的被設置為dsEdit狀態(tài)。如果該屬性值為False,那么必須提供一種將數(shù)據(jù)集設置為dsEdit狀態(tài)的方法,比如使用TDBNavigator的Edit按鈕,或者編寫代碼調(diào)用數(shù)據(jù)集的Edit方法。打開或關(guān)閉數(shù)據(jù)顯示 當應用程序要進行一次對數(shù)據(jù)集的循環(huán)操作或執(zhí)行一個查詢時,為了避免每一次的數(shù)據(jù)改動造成的數(shù)據(jù)控制組件的顯示刷新所帶來的屏幕閃爍, 應該暫

58、時中斷數(shù)據(jù)控制組件與數(shù)據(jù)集組件的關(guān)聯(lián),不顯示數(shù)據(jù),等執(zhí)行完畢后再重新建立關(guān)聯(lián)。具體做法是使用數(shù)據(jù)集組件的DisableControls方法和EnableControls方法。如下例:CustTable.DisableControls;try CustTable.First; Go to first record, which sets EOF False while not CustTable.EOF do Cycle until EOF is True begin Process each record here . CustTable.Next; EOF False on success;

59、 EOF True when Next fails on last record end;finally CustTable.EnableControls;end; 這里使用了一個TryFinally結(jié)構(gòu)是為了即使在執(zhí)行迭代過程時出現(xiàn)異常后,程序也能重新建立數(shù)據(jù)集控制組件和數(shù)據(jù)集組件間的關(guān)聯(lián)。刷新數(shù)據(jù)因為數(shù)據(jù)共享,在應用程序中訪問的數(shù)據(jù)可能同時也被其他程序訪問并修改,所以有時需要刷新正在顯示的數(shù)據(jù)。這時可以使和數(shù)據(jù)集組件的Refresh方法。該方法會從數(shù)據(jù)集中重新讀取數(shù)據(jù)來覆蓋本地緩沖區(qū)中的數(shù)據(jù)。但如果程序使用的是緩沖區(qū)更新,則需要在刷新之前向數(shù)據(jù)集提交當前緩存中的所有更新。刷新可能會產(chǎn)生意想

60、不到的結(jié)果,比如某條記錄消失,因為有另外一個用戶剛剛刪除了它。響應鼠標、鍵盤或定時器事件數(shù)據(jù)集的Enable屬性是用來決定數(shù)據(jù)集組件是否能夠響應鼠標、鍵盤或定時器事件,并傳遞信息給關(guān)聯(lián)的數(shù)據(jù)源組件。默認值是True。如果該值為False,則數(shù)據(jù)源組件不會從數(shù)據(jù)控制組件處獲得信息,數(shù)據(jù)控制組件依然顯示數(shù)據(jù),但處于灰色狀態(tài)。13.3.2 常用數(shù)據(jù)控制類組件功能簡介TDBNavigator可以向前向后移動記錄指針,可以使用該部件對單條記錄進行編輯,還可以用它來插入、刪除記錄以及刷新顯示和取消前一次的操作。 TDBText是顯示數(shù)據(jù)庫中的數(shù)據(jù)的文本框,它只能顯示數(shù)據(jù)庫表當前記錄的字段值,用戶不能對其中

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論