桌面數(shù)據(jù)庫開發(fā)_第1頁
桌面數(shù)據(jù)庫開發(fā)_第2頁
桌面數(shù)據(jù)庫開發(fā)_第3頁
桌面數(shù)據(jù)庫開發(fā)_第4頁
桌面數(shù)據(jù)庫開發(fā)_第5頁
已閱讀5頁,還剩17頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、1.編寫桌面數(shù)據(jù)庫應(yīng)用1.1. 使用數(shù)據(jù)集數(shù)據(jù)集是以行和列的形式組織起來的數(shù)據(jù)的集合。其中,每一列具有相同的數(shù)據(jù)類型,而每行是由各列指定類型的數(shù)據(jù)組成的。數(shù)據(jù)集的每一列被稱為一個(gè)字段,每一行被稱為一個(gè)記錄。V C L把數(shù)據(jù)集封裝在一個(gè)稱為TDataSet的抽象組件中。在TataSet中引入了許多用于操作和瀏覽數(shù)據(jù)集的屬性和方法。1.1.1 VCL的數(shù)據(jù)庫體系結(jié)構(gòu)在開發(fā)Delphi 3期間,V C L的數(shù)據(jù)庫體系結(jié)構(gòu)已經(jīng)有了令人注目的修改,為了在D e l p h i程序中能方便地訪問一些非B D E的數(shù)據(jù)集,它開放了數(shù)據(jù)集體系結(jié)構(gòu)。T D a t a S e t類位于整個(gè)體系結(jié)構(gòu)的頂層。T D

2、 a t a S e t是一個(gè)用來抽象地表示數(shù)據(jù)集的記錄和字段的組件。為了實(shí)現(xiàn)對(duì)一些特殊的物理數(shù)據(jù)格式的訪問,你可以在程序中覆蓋T D d a t a S e t類的方法。1.1.2 BDE數(shù)據(jù)訪問組件在組件面板的Data Access頁上可以找到用于訪問和管理B D E數(shù)據(jù)集的V C L組件,如圖2 8 - 1所示。V C L用三種組件來表達(dá)數(shù)據(jù)集: T Ta b l e、T Q u e r y和T S t o r e d P r o c。T Ta b l e是表達(dá)數(shù)據(jù)庫表中的數(shù)據(jù)和結(jié)構(gòu)的組件; T Q u e r y是利用S Q L對(duì)數(shù)據(jù)進(jìn)行查詢并返回?cái)?shù)據(jù)集的組件。T S t o r e

3、P r o c是封裝了S Q L服務(wù)器上的一個(gè)存儲(chǔ)過程的組件。本章中,我們將使用T Ta b l e組件討論數(shù)據(jù)集。稍后再介紹T Q u e r y組件。1.1.3 打開一個(gè)數(shù)據(jù)集如果是訪問S Q L服務(wù)器,那么在打開數(shù)據(jù)庫中的一個(gè)數(shù)據(jù)集之前,一定要先建立數(shù)據(jù)庫連接。當(dāng)你關(guān)閉掉數(shù)據(jù)庫中最后一個(gè)數(shù)據(jù)集時(shí),連接就會(huì)終止。建立和斷開數(shù)據(jù)庫的連接都會(huì)有一些開銷。如果你經(jīng)常執(zhí)行開關(guān)數(shù)據(jù)庫的操作,那么應(yīng)該利用T D a t a b a s e組件來管理對(duì)S Q L服務(wù)器的連接。在對(duì)數(shù)據(jù)集進(jìn)行操作之前,必須先將它打開。我們用O p e n ( )方法來實(shí)現(xiàn)。請(qǐng)看示例:Table1.Open();你也可以通過

4、將數(shù)據(jù)集的A c t i v e屬性設(shè)為Tr u e來打開它:Table1.Active:=True;使用第二種方法的開銷更小一些,因?yàn)槔肙 p e n ( )方法來實(shí)現(xiàn)最終還是要將數(shù)據(jù)集的A c t i v e屬性設(shè)為Tr u e。不過,這點(diǎn)小開銷可以忽略。當(dāng)數(shù)據(jù)集被打開后,我們就可以自由地操作和使用它了。在一系列的操作完成后,不要忘記要調(diào)用C l o s e ( )方法將它關(guān)閉。如下:Table1.Close();當(dāng)然,你也可以通過把A c t i v e屬性設(shè)為F a l s e來關(guān)閉數(shù)據(jù)集。例如:Table1.Active:=False;1.1.4 瀏覽數(shù)據(jù)集T D a t a S

5、e t提供了簡單的方法來瀏覽數(shù)據(jù)集中的記錄。First() 將當(dāng)前的記錄指針定位在數(shù)據(jù)集中的第一個(gè)記錄;L a s t ( )把當(dāng)前的記錄指針定位在數(shù)據(jù)集中的最后一個(gè)記錄; N e x t ( )和P r i o r ( )分別使當(dāng)前記錄指針向前或向后移動(dòng)一個(gè)記錄。另外, M o v e B y ( )方法用于向前或向后移動(dòng)一定數(shù)量的記錄。. BOF、E O F和循環(huán)B O F和E O F都是T D a t a S e t中布爾類型的屬性,分別表示當(dāng)前記錄是否是第一個(gè)記錄和最后一個(gè)記錄。例如,如果需要遍歷數(shù)據(jù)集中的每一條記錄,最容易實(shí)現(xiàn)的方法就是利用一個(gè)w h i l e循環(huán)來使

6、指針從第一個(gè)記錄不斷地向后移動(dòng)直到E O F為真Table1.First;While not Table1.Eof do begin Do something; Table1.Next;End;. 書簽書簽?zāi)茉跀?shù)據(jù)集中保存當(dāng)前的位置,以便以后可以回到那個(gè)位置。在D e l p h i中書簽的使用非常簡單,你只需要使用一個(gè)屬性。Delphi 用T B o o k m a r k S t r類型來表示書簽,T Ta b l e的Bookmark 屬性便是此種類型。當(dāng)從B o o k m a r k中讀值時(shí),你就獲取了一個(gè)書簽;當(dāng)你寫到它時(shí),就可以定位在書簽所指示的記錄位置。當(dāng)你對(duì)數(shù)據(jù)

7、集的某個(gè)地方感興趣并且想能標(biāo)記以便日后訪問時(shí),Var BM:TBookMarkStr;/聲明Begin BM:=Table1.BookMark;/定義 Table1.BookMark:=BM;/ 回到這個(gè)書簽標(biāo)記的位置 BM:=;End. TDataSource我們?cè)谇懊娴某绦蛑杏玫搅薚 D a t a S o u r c e組件,所以我們將在這里詳細(xì)討論這個(gè)組件。T D a t a S o u r c e是一個(gè)數(shù)據(jù)庫連接中介,它使數(shù)據(jù)訪問組件(如T Ta b l e )能向數(shù)據(jù)感知組件提供數(shù)據(jù)。它不但在數(shù)據(jù)訪問和數(shù)據(jù)感知兩方面起到了接口的作用,而且,它還包含了一些使數(shù)據(jù)操作變得

8、更簡單的屬性和事件。l T D a t a S o u r c e的S t a t e屬性表示當(dāng)前連接的底層數(shù)據(jù)集的狀態(tài)。它可以表明數(shù)據(jù)集是處于未活動(dòng)的狀態(tài)還是插入、編輯、設(shè)置鍵值或是計(jì)算字段狀態(tài)。l S t a t e屬性的值的變化會(huì)導(dǎo)致發(fā)出O n S t a t e C h a n g e事件。T D a t a S e t的O n D a t a C h a n g e事件是在數(shù)據(jù)集變成活動(dòng)狀態(tài)或數(shù)據(jù)感知組件通知數(shù)據(jù)集數(shù)據(jù)發(fā)生改變時(shí)被觸發(fā)。l On U p d a t e D a t a事件在記錄被提交或更新時(shí)被觸發(fā),在處理此事件時(shí),一般會(huì)改變數(shù)據(jù)感知組件顯示的數(shù)據(jù),這種改變依賴于數(shù)據(jù)庫

9、表的內(nèi)容。響應(yīng)此事件你可以使跟蹤程序中類似的改變。1.1.5 對(duì)字段操作. 字段值訪問字段的值需要用到T D a t a s e t的數(shù)組屬性F i e l d s 或F i e l d s B y N a m e ( )函數(shù)。l F i e l d s 0 將返回一個(gè)T F i e l d對(duì)象,它表示數(shù)據(jù)集的第一個(gè)邏輯字段。S:=Table1.Fields0.AsStringl F i e l d s B y N a m e ( )函數(shù)需要輸入字段名作為參數(shù),并返回一個(gè)字段對(duì)象。S:= Table1.FieldsByName(Name).AsString;. 字段

10、數(shù)據(jù)類型T F i e l d的D a t a Ty p e屬性可以告訴你字段的類型,所返回的字段類型只與數(shù)據(jù)庫類型有關(guān),與O b j e c tP a s c a l的數(shù)據(jù)類型無關(guān)。字段名和編號(hào)l 利用T F i e l d的F i e l d N a m e屬性能得到某個(gè)字段的字段名。S:=Table1.Fields0.FieldName;l 利用F i e l d N o屬性可以獲取某個(gè)字段對(duì)應(yīng)的編號(hào)。S:= Table1.FieldsByName(Name).FieldNo;. 操作字段數(shù)據(jù)l 編輯Table1.Edit;Table1.FieldByName

11、(Name).AsString:=LTMa;Table1.Post;Table1.Cancle;/也可以用Cancle來取消操作l 插入Table1.Insert;/或者Table1.AppendTable1.FieldByName(Name).AsString:=LTMa;Table1.Post;Table1.Cancle;/也可以用Cancle來取消操作l 刪除Table1.Last;Table1.Delete;數(shù)據(jù)集在插入、添加或編輯狀態(tài)時(shí),記住,只要離開當(dāng)前記錄,對(duì)數(shù)據(jù)的改變就會(huì)被提交給數(shù)據(jù)庫。因此,在編輯數(shù)據(jù)時(shí)要小心使用N e x t ( )、P r i o r ( )、F i r

12、s t ( )、L a s t ( )或M o v e B y ( )等方法。我們可以利用C a n c e l ( )方法來取消當(dāng)前對(duì)數(shù)據(jù)集的修改。C a n c e l ( )方法不但取消了對(duì)數(shù)據(jù)的修改,也同時(shí)取消了當(dāng)前數(shù)據(jù)集的模式狀態(tài),回到了瀏覽模式1.1.6 刷新數(shù)據(jù)集編寫數(shù)據(jù)庫程序時(shí),一定要清楚地認(rèn)識(shí)到,數(shù)據(jù)集中的數(shù)據(jù)是一直在變化的。這就是說,數(shù)據(jù)集中的數(shù)據(jù)將會(huì)不斷地被添加、刪除或修改,尤其是對(duì)于網(wǎng)絡(luò)環(huán)境。因此,你必須不停地從磁盤或內(nèi)存中重新讀取數(shù)據(jù)集中的信息來更新當(dāng)前所使用的數(shù)據(jù)集。更新數(shù)據(jù)集,可以使用TDataset 的R e f r e s h ( )方法。對(duì)R e f r e

13、 s h ( )的調(diào)用相當(dāng)于先調(diào)用C l o s e ( )方法,再調(diào)用O p e n ( )方法,但是調(diào)用R e f r e s h ( )方法要快一些。R e f r e s h ( )方法適用于所有的本地表;而對(duì)于來自S Q L數(shù)據(jù)庫服務(wù)器的數(shù)據(jù)庫,R e f r e s h ( )方法使用起來有些限制。在B D E試圖進(jìn)行R e f r e s h ( )操作之前,必須對(duì)S Q L數(shù)據(jù)庫表和查詢定義一個(gè)唯一的索引。其原因是,R e f r e s h ( )的調(diào)用總是盡可能保持記錄當(dāng)前的狀態(tài)。所以, B D E必須使用S e e k ( )來定位到當(dāng)前的位置,而S e e k ( )操

14、作只對(duì)S Q L數(shù)據(jù)集適用,而且要求有一個(gè)唯一的索引。R e f r e s h ( )并不工作于連接到S Q L數(shù)據(jù)庫的T Q u e r y組件。1.1.7 變化的狀態(tài)有時(shí)候,需要知道一個(gè)數(shù)據(jù)庫表當(dāng)前為編輯模式還是添加模式,或是否處于活動(dòng)狀態(tài),這些信息都可以通過查看TDataset 的S t a t e屬性來獲取。S t a t e屬性的類型為T D a t a S e t S t a t e,1.1.8 過濾器如果利用過濾器,只要使用Object Pascal代碼就能實(shí)現(xiàn)一些簡單的數(shù)據(jù)搜索或過濾。使用過濾器最主要的好處是不需要索引,也不需要對(duì)數(shù)據(jù)集做任何其他的準(zhǔn)備工作。當(dāng)然,過濾器和基于

15、索引的查找比起來,速度還是稍微慢一些(本章后面將會(huì)討論),但另一方面,它們對(duì)于任何類型的應(yīng)用程序都非常有用。. 過濾一個(gè)數(shù)據(jù)集D e l p h i過濾機(jī)制的一個(gè)比較普遍的作用是只顯示數(shù)據(jù)集中的一些特定記錄。這是一個(gè)簡單的兩步操作:1) 創(chuàng)建一個(gè)處理數(shù)據(jù)集的O n F i l t e r R e c o r d事件的過程。在這個(gè)過程中,根據(jù)一個(gè)或多個(gè)字段的值來決定是否要包含某個(gè)記錄。2) 將數(shù)據(jù)集的F i l t e r d屬性設(shè)為Tr u e。. FindFirst/FindNextT D a t a S e t還提供F i n d F i r s t ( )、F

16、 i n d N e x t ( )、F i n d P r i o r ( )和F i n d L a s t ( )等方法。利用這些方法可以找出那些符合篩選條件的數(shù)據(jù)記錄。這些方法被O n F i l t e r R e c o r d事件處理過程調(diào)用,來對(duì)未經(jīng)過濾的數(shù)據(jù)集進(jìn)行操作。根據(jù)O n F i l t e r R e c o r d事件處理過程中給出的過濾條件,可以找出第一個(gè)、下一個(gè)、前一個(gè)或最后一個(gè)匹配的記錄。每一個(gè)方法都不用輸入?yún)?shù),其返回值是一個(gè)表明是否找到匹配記錄的布爾值。. 定位一個(gè)記錄T D a t a S e t提供了一個(gè)名為L o c a t e (

17、)的方法。由于L o c a t e ( )使用過濾器進(jìn)行查找,所以與數(shù)據(jù)集中的任何索引都沒有關(guān)系1.2 使用TTable組件1.2.1 查找記錄當(dāng)需要查找數(shù)據(jù)庫表中的某些記錄時(shí),可以使用V C L提供的若干方法。當(dāng)使用d B A S E和P a r a d o x數(shù)據(jù)庫表時(shí),Delphi 會(huì)假定被查找的字段都已經(jīng)被定義了索引。對(duì)S Q L數(shù)據(jù)庫表,如果所查找的字段沒有定義索引,那么查詢的效率將會(huì)很低以致于無法忍受。例如,如果為一個(gè)數(shù)據(jù)庫表建立了兩個(gè)索引,第一個(gè)索引基于字段1,它是數(shù)值類型的,第二個(gè)索引基于字段2,它是字母數(shù)字類型的。這樣就可以通過這兩個(gè)索引查找特定的記錄:即調(diào)用F i n d

18、 K e y ( )或者先調(diào)用S e t K e y ( )再調(diào)用G o t o K e y ( )。.1. FindKey()T Ta b l e組件的F i n d K e y ( )方法可用來查找一個(gè)與關(guān)鍵字段匹配的記錄。F i n d K e y ( )需要傳遞一個(gè)a r r a yof const類型的參數(shù)。如果調(diào)用成功,則返回Tr u e。例如,在下面的代碼中,記錄指針被定位在這樣的記錄,其第一個(gè)字段取值為1 2 3、第二個(gè)字段中包含h e l l o字符串。If Not Table1.FindKey(123,Hello) then MessageBeep(0);如果沒有找到匹配的

19、記錄,F(xiàn) i n d K e y ( )將返回F a l s e,并且計(jì)算機(jī)發(fā)出嘀的一聲。. SetKey()和G o t o K e y ( )T Ta b l e的S e t K e y ( )方法能夠使數(shù)據(jù)庫表進(jìn)入設(shè)置鍵值的模式。在指定了查找條件后就可以調(diào)用G o t o K e y ( )來從頭到尾地搜索一個(gè)記錄。前面的例子如果改用S e t K e y ( ) . . G o t o K e y ( )來寫,則為:.3. 最接近的匹配F i n d N e a r e s t ( )與前面類似,你也可以調(diào)用F i n d N e a r e s t ( )來查找數(shù)據(jù)庫表

20、中與條件最接近匹配的記錄。例如要查找第一個(gè)字段與1 2 3最接近的記錄,并返回第一個(gè)匹配的記錄,可以使用下面的代碼:Table1.FindNearest(123);同樣,F(xiàn) i n d N e a r e s t ( )也需要傳遞一組常量作為輸入?yún)?shù),這些常量參數(shù)包含的是被查找的記錄的字段值。當(dāng)查找成功時(shí),如果K e y E x c l u s i v e屬性被設(shè)為F a l s e,則記錄指針將指在第一個(gè)匹配的記錄上;如果K e y E x c l u s i v e屬性被設(shè)為Tr u e,則記錄指針指在匹配的后一個(gè)記錄。.4. 使用哪個(gè)索引以上的方法都假設(shè)你想基于數(shù)據(jù)庫表的主索引來進(jìn)行查找

21、。如果使用副索引進(jìn)行查找,需要設(shè)置表對(duì)象的I n d e x N a m e屬性來指定一個(gè)索引。例如,如果數(shù)據(jù)庫表有一個(gè)基于C o m p a n y字段的副索引,名為B y C o m p a n y,下面的代碼查找U n i s c o公司:With Table1 do beginIndexName:=ByCompany;FindKey(Unisco);End注意在表打開的情況下,切換索引會(huì)有一些額外的開銷。如果在這時(shí)設(shè)置I n d e x N a m e屬性,可能會(huì)有一秒或更多的延遲。對(duì)于d B A S E表和P a r a d o x表來說,只能基于定義了索引的字段進(jìn)行查找。對(duì)S Q

22、L數(shù)據(jù)庫來說,如果不是針對(duì)定義了索引的字段來設(shè)置范圍的話,性能將受到損害。.5. SetRange()和ApplyRange()與F i n d K e y ( )和F i n d N e a r e s t ( )類似,S e t R a n g e ( )可以進(jìn)行復(fù)雜的操作。S e t R a n g e ( )需要傳遞兩組a r r a yof const類型的參數(shù),第一組參數(shù)表示字段取值范圍的下限,第二組則表示字段取值范圍的上限。下面的代碼從數(shù)據(jù)庫中過濾出那些第一個(gè)字段取值大于等于1 0并且小于等于1 5的記錄:Table1.SetRange(10,15);要使用A p p l y R

23、 a n g e ( )來設(shè)定取值范圍,可以按照下面的操作步驟:1) 調(diào)用S e t R a n g e S t a r t ( )方法,并修改數(shù)據(jù)庫表的F i e l d s 數(shù)組屬性來設(shè)置關(guān)鍵字段的起始值。2) 調(diào)用S e t R a n g e E n d ( )方法,并再次修改F i e l d s 數(shù)組屬性來設(shè)置關(guān)鍵字段的截止值。3) 調(diào)用A p p l y R a n g e ( )建立新的取值范圍過濾器。對(duì)前面的例子,可以這樣改寫:提示應(yīng)該盡可能利用S e t R a n g e ( )來過濾記錄,因?yàn)檫@樣會(huì)使代碼更簡潔,而且出錯(cuò)的可能性會(huì)更小。如果想要從一個(gè)數(shù)據(jù)庫表中取消一個(gè)范

24、圍過濾器,并且把數(shù)據(jù)庫恢復(fù)到調(diào)用App lyRange ( )前的狀態(tài),可以調(diào)用T Ta b l e組件的C a n c e l R a n g e ( )方法,代碼如下:2.開發(fā)C/S應(yīng)用程序摘自DElPHI5開發(fā)人員指南第29章2.1 為什么要采用客戶/服務(wù)器結(jié)構(gòu)2.2 客戶/服務(wù)器體系結(jié)構(gòu)2.3 客戶/服務(wù)器模型2.4 客戶/服務(wù)器與桌面數(shù)據(jù)庫開發(fā)的比較 面向集合與面向記錄客戶程序并不是像桌面數(shù)據(jù)庫程序那樣直接面對(duì)數(shù)據(jù)庫表,而只是面對(duì)數(shù)據(jù)的子集??蛻舫绦蛟谙蚍?wù)器請(qǐng)求數(shù)據(jù)時(shí),得到的數(shù)據(jù)可能是由一個(gè)或多個(gè)表中的字段構(gòu)成的,而請(qǐng)求是通過結(jié)構(gòu)化查詢語言( S Q L )實(shí)現(xiàn)的。通過S Q L,

25、客戶端可以限制從服務(wù)器返回的記錄數(shù)??蛻舳送ㄟ^S Q L語句從服務(wù)器上得到結(jié)果是服務(wù)器上的數(shù)據(jù)的一個(gè)子集。這一點(diǎn)很重要,因?yàn)閷?duì)于桌面數(shù)據(jù)庫應(yīng)用程序來說,它通過網(wǎng)絡(luò)所得到是整個(gè)數(shù)據(jù)庫表。顯然,數(shù)據(jù)庫表越大,網(wǎng)絡(luò)的流量就越大。客戶/服務(wù)器系統(tǒng)則不同,它只通過網(wǎng)絡(luò)傳送客戶請(qǐng)求的數(shù)據(jù),因而網(wǎng)絡(luò)流量較小,對(duì)網(wǎng)絡(luò)的要求也較低。這個(gè)區(qū)別也影響了對(duì)S Q L數(shù)據(jù)集的瀏覽性。例如第一條、最后一條、下一條和上一條記錄等概念,對(duì)基于S Q L的數(shù)據(jù)集來說不是固有的。尤其是當(dāng)查詢結(jié)果是由多個(gè)數(shù)據(jù)庫表組成的情況下更是如此。許多S Q L服務(wù)器提供了可翻滾的指針,用于瀏覽S Q L結(jié)果集。盡管如此,這與桌面數(shù)據(jù)庫的瀏覽還

26、是不同的,因?yàn)楹笳咧苯俞槍?duì)數(shù)據(jù)庫表進(jìn)行瀏覽。 數(shù)據(jù)安全S Q L數(shù)據(jù)庫處理數(shù)據(jù)安全的方式與桌面數(shù)據(jù)庫是不同的。S Q L數(shù)據(jù)庫不僅可以對(duì)數(shù)據(jù)庫進(jìn)行口令驗(yàn)證,而且還能夠針對(duì)特定的數(shù)據(jù)庫對(duì)象進(jìn)行限制,包括視圖、數(shù)據(jù)庫表和存儲(chǔ)過程等。這意味著用戶訪問能夠在服務(wù)器端定義,來基于用戶的需要顯示數(shù)據(jù)。通常,S Q L數(shù)據(jù)庫允許通過G R A N T或R E V O K E命令向一個(gè)用戶或一組用戶授予或收回權(quán)限。因此,可以在S Q L數(shù)據(jù)庫中定義一組用戶。這些權(quán)限可以應(yīng)用于任何一種已經(jīng)提到的數(shù)據(jù)庫對(duì)象。 記錄鎖定方法鎖定是一種機(jī)制,使得多個(gè)用戶可以對(duì)同一個(gè)數(shù)據(jù)庫提交并發(fā)的S Q L事務(wù)。鎖定級(jí)別有多種,不同

27、的服務(wù)器有不同的級(jí)別。表一級(jí)的鎖定主要用于限制對(duì)一個(gè)正在處理事務(wù)的數(shù)據(jù)庫表的訪問。盡管這種方式允許并行的處理,但這種鎖定機(jī)制速度很慢,因?yàn)槎鄠€(gè)用戶往往要共享同一個(gè)表。頁面級(jí)鎖定是一種改進(jìn)的鎖定技術(shù)。用這種技術(shù),服務(wù)器可以把數(shù)據(jù)的某一塊鎖定在磁盤上,也就是所謂的頁面。當(dāng)一個(gè)事務(wù)正在對(duì)某頁進(jìn)行處理時(shí),其他事務(wù)就不能更新該頁上的數(shù)據(jù)。由于數(shù)據(jù)往往分布在數(shù)百個(gè)頁面上,因此多個(gè)事務(wù)同時(shí)操作同一個(gè)頁面的可能性很小。有些服務(wù)器還提供了記錄級(jí)的鎖定機(jī)制,能夠鎖定數(shù)據(jù)庫表中的某一行。不過,這樣會(huì)大大增加鎖定信息的維護(hù)工作。桌面數(shù)據(jù)庫采用所謂的保守或明確的鎖定策略。這意味著,無法改變那些當(dāng)前正在被其他用戶更新的記

28、錄。如果試圖訪問這樣的記錄,將會(huì)出錯(cuò),錯(cuò)誤信息提示除非先前那個(gè)用戶釋放該記錄,否則無法訪問。S Q L數(shù)據(jù)庫采用所謂的優(yōu)化鎖定策略。這種技術(shù)并不限制訪問當(dāng)前正在被其他用戶訪問的記錄,可以照常對(duì)它進(jìn)行編輯,并請(qǐng)求服務(wù)器保存修改后的數(shù)據(jù)。不過,在記錄被保存之前,首先會(huì)與服務(wù)器中的備份進(jìn)行比較,因?yàn)樵诓榭春托薷倪@條記錄的同時(shí),它可能已被其他用戶更新。如果該記錄已被其他用戶修改,則會(huì)導(dǎo)致一個(gè)錯(cuò)誤,提示在取得記錄后,它已經(jīng)被更新。作為一個(gè)開發(fā)人員,在設(shè)計(jì)客戶程序時(shí)應(yīng)該考慮到這一點(diǎn),客戶/服務(wù)器程序尤其要注意到這種情況,而在桌面數(shù)據(jù)庫中就不會(huì)發(fā)生。 數(shù)據(jù)完整性對(duì)于S Q L數(shù)據(jù)庫,可以對(duì)服務(wù)器中的數(shù)據(jù)進(jìn)行

29、更健壯的完整性約束。盡管桌面數(shù)據(jù)庫也內(nèi)建了完整性驗(yàn)證的功能,但需要在應(yīng)用程序的代碼中定義一些業(yè)務(wù)規(guī)則。相對(duì)而言, S Q L數(shù)據(jù)庫允許在服務(wù)器端定義這些規(guī)則。這一點(diǎn)的好處是,不僅可以強(qiáng)制所有的客戶端程序都接受同一套規(guī)則的約束,而且可以集中維護(hù)這些規(guī)則。完整性約束是在服務(wù)器上創(chuàng)建數(shù)據(jù)庫表時(shí)定義的,完整性約束包括有效性、唯一性和參照性。完整性約束也可以在S Q L存儲(chǔ)過程中定義。例如,在處理一個(gè)訂單之前,可以先檢查顧客的信用。 面向事務(wù)S Q L數(shù)據(jù)庫是面向事務(wù)的。這意味著,對(duì)數(shù)據(jù)庫的修改不是像桌面數(shù)據(jù)庫那樣直接針對(duì)數(shù)據(jù)庫表進(jìn)行的,而是由客戶請(qǐng)求服務(wù)器進(jìn)行修改,服務(wù)器用一個(gè)事務(wù)來完成這一批操作。為

30、了確保對(duì)數(shù)據(jù)庫的修改能夠有效,必須完整地提交事務(wù)。如果事務(wù)中的任何一個(gè)操作失敗,整個(gè)事務(wù)就會(huì)被回滾,換句話說,就是放棄。事務(wù)能夠保證服務(wù)器上數(shù)據(jù)的一致性。還是以前面提到過的存貨系統(tǒng)為例,當(dāng)顧客提交了一份訂單后,O R D E R S表必須更新。另外, PA RT S表也必須相應(yīng)地把零件數(shù)減少。如果因?yàn)槟撤N原因,系統(tǒng)在更新O R D E R S表和PA RT S表之間出錯(cuò),PA RT S表中的零件數(shù)就不能反映實(shí)際情況。但是,如果把整個(gè)操作放在一個(gè)事務(wù)中,除非整個(gè)事務(wù)正確地提交,否則,沒有一個(gè)表會(huì)有任何改變。在Delphi 5中,對(duì)于事務(wù)既可以在服務(wù)器層進(jìn)行控制,也可以在客戶層進(jìn)行控制。2.5 S

31、QL在客戶/服務(wù)器開發(fā)中的角色2.6 Delphi 客戶/服務(wù)器開發(fā)Delphi 5提供了一些數(shù)據(jù)庫對(duì)象組件,它們封裝了B D E的功能。這樣,開發(fā)數(shù)據(jù)庫應(yīng)用程序就不必知道B D E的功能。其次, Delphi 5提供了數(shù)據(jù)感知組件可以與數(shù)據(jù)訪問組件彼此通信,這樣,建立數(shù)據(jù)庫應(yīng)用程序的界面就變得簡單。SQL Links為連接O r a c l e、S y b a s e、I n f o r m i x、Microsoft SQL Server、D B 2和I n t e r B a s e提供了專門的驅(qū)動(dòng)程序Delphi 5還包含了M I D A S技術(shù),“ M I D A S:Multiti

32、er Distributed Application Services Suite ”。最后, D e l p h i允許使用CORBA(Comman Object Request Broker Architecture) 來開發(fā)分布式應(yīng)用程序。C O R B A規(guī)范已經(jīng)被OMG(Object Management Group)采用。通過C O R B A技術(shù),可以創(chuàng)建面向?qū)ο蟮姆植际綉?yīng)用程序2.7 服務(wù)器:后端設(shè)計(jì)2.8 客戶:前端開發(fā) 使用TDatabase組件T D a t a b s e組件可以更有效地控制數(shù)據(jù)庫的連接,包括: 建立一個(gè)永久的數(shù)據(jù)庫連接。 覆蓋默認(rèn)的服務(wù)器登錄。 創(chuàng)建應(yīng)

33、用程序級(jí)的B D E別名。 控制事務(wù)并指定事務(wù)的隔離級(jí)別。.1. 應(yīng)用程序級(jí)的連接使用T D a t a b a s e組件的原因之一是,可以通過它建立一個(gè)應(yīng)用程序級(jí)的別名。與B D E配置程序建立的別名不同的是,T D a t a b a s e組件建立的別名只在本項(xiàng)目中有效。如果要與其他應(yīng)用程序共享這個(gè)別名,可以把T D a t a b a s e組件放到可共享的數(shù)據(jù)模塊( T D a t a M o d u l e )中,然后把數(shù)據(jù)模塊放到對(duì)象庫中,這樣,其他應(yīng)用程序就可以使用它了。要建立一個(gè)應(yīng)用程序級(jí)的別名,可以設(shè)置T D a t a b a s e . D a t a b a s e

34、 N a m e屬性。至于T D a t a b a s e要連接的數(shù)據(jù)庫的B D E別名則由T D a t a b a s e . A l i a s N a m e屬性來指定。.2. 安全控制T D a t a b a s e通過控制用戶的登錄過程來限制用戶對(duì)服務(wù)器數(shù)據(jù)的訪問。在登錄時(shí),用戶必須給出合法的用戶名和口令才能訪問數(shù)據(jù)。默認(rèn)情況下,當(dāng)試圖連接數(shù)據(jù)庫時(shí),會(huì)打開一個(gè)標(biāo)準(zhǔn)的對(duì)話框。處理登錄有幾種方式。首先,完全可以跳過登錄,讓用戶不需登錄就可以訪問服務(wù)器數(shù)據(jù)。其次,可以根據(jù)需要調(diào)出幾種不同的登錄對(duì)話框,以便在將用戶名和口令傳給服務(wù)器進(jìn)行正常的檢查之前進(jìn)行你自己的合法性檢查。最后,可以允

35、許用戶在不關(guān)閉應(yīng)用程序的情況下退出再重新登錄。下面將詳細(xì)介紹這些技術(shù)。.2.1 自動(dòng)登錄不讓登錄對(duì)話框出來如果不想出現(xiàn)登錄對(duì)話框,必須設(shè)置T D a t a b a s e的下列屬性:l A l i a s N a m e 設(shè)為一個(gè)已有的用B D E配置工具定義的B D E別名,通常與T Ta b l e、T Q u e r y組件的A l i a s屬性相同。l D a t a b a s e N a m e 設(shè)為一個(gè)應(yīng)用程序級(jí)的別名,這個(gè)別名代表T Ta b l e、T Q u e r y或T S t o r e P r o c組件要訪問的數(shù)據(jù)庫。這些組件將使用該值作為它們的A l i a

36、 s屬性值。l L o g i n P r o m p t 設(shè)為F a l s e,這樣,T D a t a b a s e組件將從P a r a m s屬性中獲取用戶名和口令。P a r a m s 給出用戶名和口令。為此,必須打開一個(gè)字符串編輯器來設(shè)置這些值。l 設(shè)置了這些屬性后,必須把T Ta b l e、T Q u e r y或T S t o r e P r o c的A l i a s屬性值設(shè)為T D a t a b a s e的D a t a b a s e -N a m e屬性值,這樣,就把這些數(shù)據(jù)集組件與T D a t a b a s e連接起來?,F(xiàn)在,可以把T D a t a

37、b a s e . C o n n e c t e d的屬性設(shè)為Tr u e。這樣,當(dāng)應(yīng)用程序連接到服務(wù)器時(shí),將不提示輸入用戶名和口令,因?yàn)镻 a r a m s屬性中已經(jīng)給出了用戶名和口令。.2.2 自定義的登錄對(duì)話框在某些場合,可能需要為用戶提供自定義的登錄對(duì)話框。例如,你可能想提示用戶在對(duì)話框中輸入除了用戶名和口令之外的附加信息,或者希望在程序開始時(shí)能出現(xiàn)更漂亮的登錄對(duì)話框,而不是默認(rèn)的那種。無論是何種情況,處理都非常簡單。l 首先,把T D a t a b a s e . L o g i n P r o m p t屬性設(shè)為Tr u e,這樣就不會(huì)顯示默認(rèn)的登錄對(duì)話框, 并保證觸發(fā)O n

38、 L o g i n事件。l 不過,現(xiàn)在不要通過P a r a m s屬性提供用戶名和口令,而要編寫處理T D a t a b a s e . O n L o g i n事件的處理過程。這個(gè)事件處理過程在T D a t a b a s e . C o n n e c t e d屬性和T D a t a b a s e . L o g i n P r o m p t被設(shè)為Tr u e時(shí)被調(diào)用。下面的函數(shù)自定義了一個(gè)登錄窗口,并返回用戶名和密碼:.2.3 從當(dāng)前會(huì)話退出.3 事務(wù)控制用Delphi 5編寫的客戶程序可以通過T D a t a b a s e的有關(guān)屬性和方法來處理事務(wù)。下面將介紹怎樣

39、在Delphi 5程序中處理事務(wù)。.3.1 隱式和顯式的事務(wù)控制Delphi 5既可以隱式又可以顯式地處理事務(wù),默認(rèn)是隱式的。隱式的事務(wù)是以逐行的方式開始和提交的。這意味著,當(dāng)調(diào)用P o s t方法或P o s t方法被V C L的代碼自動(dòng)調(diào)用時(shí),由于是逐行處理的,因此可能導(dǎo)致網(wǎng)絡(luò)流量增加,從而降低效率。顯式的事務(wù)處理又分下面兩種方式。l 一種方式是調(diào)用T D a t a b a s e組件的S t a r t Tr a n s a c t i o n ( )、C o m m i t ( )或R o l l B a c k ( )等方法;l 另一種方式是通過T Q u e r y組件的直通(

40、p a s s - t h r o u g h ) S Q L命令來實(shí)現(xiàn)的,由于顯式事務(wù)的網(wǎng)絡(luò)流量較小,而且代碼較安全,建議采用這種方式。.3.2處理事務(wù) T D a t a b a s e的方法中有三個(gè)是與數(shù)據(jù)庫事務(wù)有關(guān)的,分別是: S t a r t Tran s a c t i o n ( )、C o m m i t ( )和R o l l B a c k ( )。l S t a r t Tr a n s a c t i o n ( )啟動(dòng)一個(gè)事務(wù),隔離級(jí)別由T D a t a b a s e . Tr a n s I s o l a t i o n屬性指定。在調(diào)用S t a r t T

41、r a n -s a c t i o n ( )之后對(duì)數(shù)據(jù)庫所做的任何修改都成為事務(wù)的一部分。l 如果對(duì)數(shù)據(jù)庫的所有修改都成功,則調(diào)用T D a t a b a s e . C o m m i t ( )方法把所有修改一次保存到數(shù)據(jù)庫中。l 反之,如果發(fā)生了錯(cuò)誤,則調(diào)用T D a t a b a s e . R o l l B a c k ( )方法來取消所有的修改。.3.3 SQL直通模式S Q L直通( p a s s - t h r o u g h )模式能夠使Delphi 5數(shù)據(jù)庫應(yīng)用程序與B D E共享到數(shù)據(jù)庫服務(wù)器的連接。Delphi 5的程序中如果調(diào)用了BDE API,則可能需要

42、使用B D E連接。直通模式是在B D E配置工具中設(shè)置的。這種模式有三個(gè)選項(xiàng):l SHARED AUTO C O M M I T 以逐行方式處理數(shù)據(jù)庫事務(wù),主要用于桌面數(shù)據(jù)庫應(yīng)用程序。在客戶/服務(wù)器環(huán)境下,這將導(dǎo)致網(wǎng)絡(luò)流量增加,因此不推薦這個(gè)選項(xiàng),但這是Delphi 5應(yīng)用程序的默認(rèn)選項(xiàng)。l SHARED NOAUTO C O M M I T Delphi 5 程序必須通過調(diào)用T D a t a b a s e的S t a r t Tr a n s a c t i o n ( )、C o m m i t ( )和R o l l B a c k ( )方法來顯式地啟動(dòng)、提交和回滾事務(wù)。l NO

43、T SHARED B D E和T Q u e r y組件提交的直通S Q L語句不共享同一個(gè)連接。這意味著, S Q L代碼可以不受B D E功能的限制,可以發(fā)揮服務(wù)器的特性。如果不想使用直通式S Q L但又想對(duì)事務(wù)進(jìn)行更多的控制,可以把這個(gè)選項(xiàng)設(shè)為SHARED NOAUTOC O M M I T并自行處理事務(wù)。在大多數(shù)情況下,這種模式是可以的。但是,在多用戶環(huán)境下,如果某條記錄需要頻繁地更新,則可能發(fā)生沖突。.3.4 隔離級(jí)別隔離級(jí)別是指一個(gè)事務(wù)對(duì)其他事務(wù)正在訪問的數(shù)據(jù)具有怎樣的可見性。T D a t a b a s e . Tr a n s I s o l a t i o n屬性用于指定一

44、個(gè)事務(wù)的隔離級(jí)別。對(duì)于Tr a n s I s o l a t i o n屬性,可以有三種取值,分別代表三種隔離級(jí)別:l t i D i r R e a d 最低的隔離級(jí)別。具有該級(jí)別的事務(wù)可以讀取其他事務(wù)正在修改但還沒有提交的數(shù)據(jù)。l t i R e a d C o m m i t t e d 這是默認(rèn)的隔離級(jí)別。具有該級(jí)別的事務(wù)只能讀取那些已被其他事務(wù)提交的數(shù)據(jù)。l t i R e p e a t a b l e R e a d 這是最高的隔離級(jí)別。具有這種隔離級(jí)別的事務(wù)無法讀到另一個(gè)事務(wù)正在讀取的數(shù)據(jù)。不同的服務(wù)器所支持的隔離級(jí)別也可能不同。Delphi 5通常使用t i R e a d

45、 C o m m i t t e d級(jí)別,除非服務(wù)器不支持該級(jí)別。 TQuery比TTable優(yōu)秀有人認(rèn)為開發(fā)客戶/服務(wù)器結(jié)構(gòu)的前端與開發(fā)桌面數(shù)據(jù)庫應(yīng)用程序是相同或類似的,這是一個(gè)較為普遍的錯(cuò)誤認(rèn)識(shí)。從使用T Ta b l e還是T Q u e r y的比較中,我們可以體會(huì)到這種區(qū)別。下面將討論使用T Ta b l e組件的優(yōu)缺點(diǎn),分析在什么情況下應(yīng)該使用它、什么情況下不應(yīng)該使用它。通過這些分析,你將會(huì)理解為什么使用T Q u e r y組件比較好。l T Ta b l e組件能夠操作整個(gè)數(shù)據(jù)庫表、瀏覽前后的記錄或者轉(zhuǎn)到某個(gè)特定的記錄。不過,這些概念對(duì)S Q L數(shù)據(jù)庫服務(wù)器來說則是不適用的。關(guān)

46、系型數(shù)據(jù)庫是以數(shù)據(jù)集的形式被訪問的。因此, S Q L數(shù)據(jù)庫中沒有下一條記錄、前一條記錄和后一條記錄等概念。而在T Ta b l e組件中,這些概念是非常普遍的。盡管有些S Q L數(shù)據(jù)庫提供了可滾動(dòng)的指針,但這不是標(biāo)準(zhǔn)的,l 當(dāng)我們通過T Ta b l e組件操作S Q L數(shù)據(jù)庫時(shí),最重要的一點(diǎn)就是,通過T Ta b l e組件發(fā)出的數(shù)據(jù)庫操作命令必須轉(zhuǎn)換為S Q L代碼才能被S Q L數(shù)據(jù)庫識(shí)別和執(zhí)行。這不僅限制了對(duì)數(shù)據(jù)庫的訪問,而且也大大降低了效率。l 雖然T Ta b l e的F i n d K e y ( )方法能夠搜索記錄,但對(duì)于S Q L數(shù)據(jù)庫來說此方法是有限制的。首先,F(xiàn) i n

47、 d K e y ( )只能基于定義了索引的字段進(jìn)行搜索,而T Q u e r y則沒有這個(gè)限制,因?yàn)樗怯肧 Q L來查詢記錄的。盡管TTable.FindKey( )最終還是用S E L E C T命令來對(duì)數(shù)據(jù)庫表進(jìn)行操作的,但是,使用F i n d K e y ( )得到的結(jié)果集中包含了所有的字段,即使通過T Ta b l e的字段編輯器只選擇了其中部分字段。 使用TQuery組件3使用ADO摘自Master Delphi7第15章3.1Microsoft數(shù)據(jù)訪問組件(MDAC) 3.2使用dbGo組件 3.3使用Jet引擎 3.4光標(biāo) ADO集合有兩個(gè)基礎(chǔ)屬性會(huì)對(duì)程序產(chǎn)生基礎(chǔ)性的影響,

48、并且不可分割的相互鏈接在一起,它們是:CursorLocation和CursorType光標(biāo)位置CursorLocation屬性運(yùn)行程序員來指定誰控制數(shù)據(jù)的提取和更新,有兩個(gè)選擇:客戶機(jī)(clUseClient)和服務(wù)器(clUseServer)。所作的選擇會(huì)影響數(shù)據(jù)集合的功能、性能和可擴(kuò)張性。.1客戶端光標(biāo)(clUseClient)客戶端光標(biāo)由ADO Cursor Engine負(fù)責(zé)管理,當(dāng)數(shù)據(jù)集打開的時(shí)候數(shù)據(jù)從服務(wù)器提取到客戶端,并保存在內(nèi)存中,由ADO Cursor Engine管理更新和操作.2服務(wù)器端光標(biāo)(clUseServer)光標(biāo)類型.1只向前光標(biāo).2靜態(tài)光標(biāo).3鍵集光標(biāo).4動(dòng)態(tài)光

49、標(biāo)要求與結(jié)果無記錄計(jì)數(shù)客戶端索引IndexFieldName,ADO不從數(shù)據(jù)源讀數(shù),而是在內(nèi)存中完成的。復(fù)制Clone方法可以復(fù)制任意的ADO數(shù)據(jù)集合。復(fù)制不會(huì)影響到最初的地副本,它們擁有自己的記錄指針和其它狀態(tài)信息,并且可以擁有不同的Active記錄3.5事務(wù)處理 ADO的事務(wù)處理被ADOConnection組件控制,使用BeginTrasaction、CommitTrasaction、RollbackTrasaction嵌套事務(wù) ADOConnection屬性 鎖定類型ADO支持四種不同的方法來鎖定用于更新的數(shù)據(jù)(LockType有4種屬性),它們是:ltReadOnly,ltPessim

50、istic,ltOptimistic,ltBatchOptimistic.1 ltReadOnly:指定數(shù)據(jù)是只讀的,并且不能更新.2 ltPessimistic消極鎖定:消極鎖定假設(shè)用戶將有很大的可能性會(huì)同時(shí)更新相同的記錄,并出現(xiàn)沖突。為防止這樣的沖突,當(dāng)編輯開始時(shí)記錄將被鎖定,并一直持續(xù)到更新完成或者取消操作為止。第二個(gè)試圖編輯相同記錄的用戶將不能成功鎖定記錄,并會(huì)收到一條“不能更新,當(dāng)前記錄已被鎖定”的異常。l 優(yōu)點(diǎn):用戶可以知道他們是否可以開始編輯一條記錄,以及是否能成功的保存他們的更新l 缺點(diǎn):用戶在鎖定與接觸鎖定的時(shí)間上需要控制,防止用戶開始編輯一條記錄就離開了,而使此記錄一直被鎖

51、定。常用TTime設(shè)備,在鍵盤與鼠標(biāo)休眠一定時(shí)間后解除鎖定。ltOptiimstic消極鎖定必須使用一個(gè)服務(wù)器端的光標(biāo)。3.6更新數(shù)據(jù) 聯(lián)合查詢DataSet的更新ADO支持批更新,并且ADO的連接是天生可以“更新的”。在一個(gè)ADO連接中,每個(gè)字段對(duì)象都知道它屬于哪個(gè)數(shù)據(jù)庫表。例如由表Products和表Supplier連接查詢生產(chǎn)ADODataSetJointData,如果更新的字段屬于Products表,則會(huì)生成一條針對(duì)Products表的SQL Update語句。如果更新2個(gè)字段分別屬于Products表和Supplier表,則會(huì)生產(chǎn)2條分別針對(duì)Produts表和Supplier表的SQ

52、L Update語句ADO解決方案的最大問題是刪除一個(gè)連接的一行時(shí),操作將會(huì)失敗。假如用戶只想刪除Products表的數(shù)據(jù),可以用下面代碼來指定刪除只針對(duì)Products表ADOQuery1.PropertiesUnique Table.Value:=Products;AdoQuery1.Recordset.Properties'Unique   Table'.Value   :='tablename'  批更新使用批更新的時(shí)候,對(duì)記錄做的任何修改都在內(nèi)存中進(jìn)行,然后將整批的修改作為一個(gè)操作來提交,其用法如下:l 在打開數(shù)據(jù)集合前,

53、將LockType設(shè)為ltBatchOptimisticl 將CursorLocation設(shè)為clUseClient,因?yàn)榕率怯葾DO的ADO Cursor Engine管理的。l 然后所有的修改作為增量,在內(nèi)存中進(jìn)行l(wèi) 使用UpdateBatch,更新永久有效l 使用CancleBatch或CancleUpdate放棄整批的更新 ADO的其它重要屬性.1 UpdateStatusUpdateStatus用于識(shí)別記錄的狀態(tài)(插入、更新、刪除或未修改),它特別適用于在Grid中用不同顏色來突出記錄.2 UpdatesPendingADO數(shù)據(jù)集的UpdatesPending屬性,在數(shù)據(jù)集已經(jīng)修

54、改但是還沒有應(yīng)用的時(shí)候?yàn)門rue,這在窗體的OnCloseQuery事件中用于提示還有未保存的數(shù)據(jù): Procedure TForm1.FormCloseQuery(Sender:TObject;var CanClose :Boolean) Begin CanClose:=True; If ADODataSet1.UpdatesPending then CanClose:=MessageDlg(); End;.3 FilterGroupADO數(shù)據(jù)集還有一個(gè)名為FilterGroup的屬性,它是一個(gè)基于記錄狀態(tài)的過濾器。為了防止使用FilterGroup時(shí)移動(dòng)記錄指針,采用復(fù)制的方法來判斷是否有修改過的記錄:Function ADOUpdatesPending(ADODataSet :TCustomADODataSet):BooleanVarClone:TADODataSet;Beg

溫馨提示

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

評(píng)論

0/150

提交評(píng)論