陳蘭貞 陳玉祥
前言
Visual FoxPro數(shù)據(jù)庫(kù)開(kāi)發(fā)工具(以下簡(jiǎn)稱 VFP)具有易于掌握、易于開(kāi)發(fā)、項(xiàng)目管理方便靈活、擁有強(qiáng)大編程語(yǔ)言、對(duì)系統(tǒng)資源要求不高等特性。長(zhǎng)期以來(lái),VFP以其小而巧的特點(diǎn),受到中、小型數(shù)據(jù)庫(kù)開(kāi)發(fā)者的青睞。隨著VFP程序應(yīng)用的深入,我們會(huì)發(fā)現(xiàn)VFP數(shù)據(jù)庫(kù)文件(.dbc)、表文件(.dbf)存在一些弊端,因?yàn)檫@些固有的問(wèn)題,開(kāi)發(fā)人員不得不去尋求更安全的開(kāi)發(fā)策略,保證我們的應(yīng)用程序,穩(wěn)定可靠,安全無(wú)患。通常的解決辦法是使用結(jié)構(gòu)化查詢語(yǔ)言服務(wù)器SQL Server,提供后臺(tái)數(shù)據(jù)服務(wù)。
一、做在前面
1.在設(shè)計(jì)VFP表單時(shí),改善對(duì)DBF表的訪問(wèn):
通常,F(xiàn)oxPro應(yīng)用程序都使用DBF表來(lái)存儲(chǔ)數(shù)據(jù)。對(duì)于單用戶的應(yīng)用DBF表是很有效的。可以獨(dú)占的打開(kāi)表并綁定表的字段到表單控件(如文本框和復(fù)選框)。可以不再使用內(nèi)存變量來(lái)復(fù)制數(shù)據(jù)字段以用于增加或編輯。可以簡(jiǎn)單的把緩沖模式設(shè)為3(開(kāi)放式行緩沖)以有效地把表單與數(shù)據(jù)字段分離開(kāi)來(lái),然后發(fā)出TableUpdate(.T.)以永久地修改數(shù)據(jù),或者發(fā)出TableRevert(.T.)以忽略所發(fā)生的改變。
對(duì)于多用戶的應(yīng)用,只需要以共享方式(SHARED)打開(kāi)所有的DBF表。
通常,在表單的數(shù)據(jù)環(huán)境里我們會(huì)加入所有的表和視圖以便其自動(dòng)打開(kāi)。由于在表單控件創(chuàng)建前所有別名已經(jīng)打開(kāi)(具體的說(shuō)表單對(duì)象在表單的Load和Init事件間生成),使用表單數(shù)據(jù)環(huán)境可以節(jié)省我們的開(kāi)發(fā)時(shí)間。當(dāng)把一個(gè)表加入表單的數(shù)據(jù)環(huán)境里,當(dāng)表打開(kāi)時(shí),表的記錄指針將會(huì)移動(dòng)指向當(dāng)前索引標(biāo)識(shí)的第一個(gè)記錄。
但是使用數(shù)據(jù)環(huán)境,在多用戶環(huán)境下,要有效控制數(shù)據(jù)表,卻不是很順利,可能會(huì)有很多“表已打開(kāi)的”的提示。
所以,要開(kāi)發(fā)多用戶應(yīng)用系統(tǒng),我們經(jīng)常用自己的代碼,在表單的Load事件里打開(kāi)光標(biāo)和表。這樣,我們可以控制得更多。而這種控制,將會(huì)讓我們?cè)谝院竺鎸?duì)更多用戶時(shí),不再措手不及。
2.建立數(shù)據(jù)字典
在表單的Load事件里,以上面調(diào)用OpenDBF過(guò)程的方式來(lái)創(chuàng)建每一個(gè)光標(biāo),這是一種很好的方法。但是這種方法還是存在一定的隱患,雖然這種幾率是非常的小。OpenDBF.PRG打開(kāi)的是物理存在的表,萬(wàn)一該表被誤刪了或損壞了,這么辦?相信每位程序員都會(huì)有自己的應(yīng)對(duì)策略。我的方法是建一個(gè)所有臨時(shí)表的備份,當(dāng)打開(kāi)表不成功時(shí),用備份覆蓋一下。
有一種更好的方法:可以建立一個(gè)包含所有需要?jiǎng)?chuàng)建的光標(biāo)的信息的數(shù)據(jù)字典,然后調(diào)用下面講述的CreatCursor()函數(shù)。用這種方法,雖然前期工作要多一點(diǎn),但是臨時(shí)表現(xiàn)場(chǎng)建立,那“表不存在”,“不是一個(gè)表”等錯(cuò)誤提示,想出來(lái)也沒(méi)人去叫它了。
二、建立SPT連接
為了使用SPT,程序必須建立一個(gè)服務(wù)器連接。通常使用SQLConnect()函數(shù)或SQLStringConnect()函數(shù)來(lái)建立該連接。
1.方式一:使用SQLConnect()函數(shù)建立SPT連接
SQLConnect()使用DSN,使用“控制面板”中的“ODBC數(shù)據(jù)源管理器”創(chuàng)建某個(gè)數(shù)據(jù)庫(kù)的ODBC 數(shù)據(jù)資源名,即DSN,這樣以后可以通過(guò)使用數(shù)據(jù)庫(kù)DSN連接具體的數(shù)據(jù)庫(kù)。
“ODBC數(shù)據(jù)源管理器”提供了三種DSN,分別為用戶DSN、系統(tǒng)DSN和文件DSN。其中,用戶DSN會(huì)把相應(yīng)的配置信息保存在Windows的注冊(cè)表中,但是只允許創(chuàng)建該DSN的登錄用戶使用。系統(tǒng)DSN同樣將有關(guān)的配置信息保存在系統(tǒng)注冊(cè)表中,但是與用戶DSN不同的是系統(tǒng)DSN允許所有登錄服務(wù)器的用戶使用。
與上述兩種數(shù)據(jù)庫(kù)DSN不同,文件DSN把具體的配置信息保存在硬盤(pán)上的某個(gè)具體文件中。文件DSN允許所有登錄服務(wù)器的用戶使用,而且即使在沒(méi)有任何用戶登錄的情況下,也可以提供對(duì)數(shù)據(jù)庫(kù)DSN的訪問(wèn)支持。此外,因?yàn)槲募﨑SN被保存在硬盤(pán)文件里,所以可以方便地復(fù)制到其它機(jī)器中。這樣,用戶可以不對(duì)系統(tǒng)注冊(cè)表進(jìn)行任何改動(dòng)就可直接使用在其它機(jī)器上創(chuàng)建的DSN。
在以上三種數(shù)據(jù)庫(kù)DSN中,建議大家選擇系統(tǒng)DSN或文件DSN,如果更喜歡文件DSN的可移植性,可以通過(guò)在NT系統(tǒng)下設(shè)定文件的訪問(wèn)權(quán)限獲得較高的安全保障。
2.方式二: 使用連接串SQLStringConnect()函數(shù)建立SPT連接
StrCmd=[Server=(local);Driver={SQL Server};Database=One;UserID=sa;pwd=sa;]
Handle = SQLStringConnect ( strCmd )
lr= SQLExec ( Handle, [SELECT * FROM CUSTOMER], [AllCusts] )
這將返回整個(gè)customer表給命名為“AllCusts”的光標(biāo)。
3.上面兩種方法之一取回需要的數(shù)據(jù)后,用SQLDisconnect(句柄) 語(yǔ)句來(lái)關(guān)閉連接
SQLDisconnect( lh )
三、從SQL Server返回?cái)?shù)據(jù)到本地光標(biāo)
可是,上面返回的光標(biāo)并不是我們綁定于表單控件的光標(biāo),因?yàn)镾QLExec()總是創(chuàng)建一個(gè)新的光標(biāo),我們不能使用已經(jīng)存在的光標(biāo)作為SQLExec()的第三個(gè)參數(shù)。當(dāng)我們?cè)谠O(shè)計(jì)表單時(shí),經(jīng)常從表單數(shù)據(jù)環(huán)境的表里拖出字段到屏幕上,于是自動(dòng)設(shè)置該表的這個(gè)字段為該控件的綁定數(shù)據(jù)源(ControlSource)。
該如何在不斷開(kāi)綁定的情況把這兩者連接起來(lái)?鑒于我們的經(jīng)驗(yàn),可以使用了一個(gè)簡(jiǎn)單的解決辦法,僅以較小的性能損失用以免除大量的編程。在表單的Load事件里,我們已按“做在前面”所說(shuō),創(chuàng)建好了我們需要的光標(biāo),并把表單控件梆定于它。然后,當(dāng)我們用SPT從SQL Server返回?cái)?shù)據(jù)給SQL光標(biāo)時(shí),只需要簡(jiǎn)單地ZAP本地光標(biāo)并把返回的SQL光標(biāo)數(shù)據(jù)追加進(jìn)來(lái),或者直接把返回的SQL光標(biāo)數(shù)據(jù)追加到Load事件里打開(kāi)的光標(biāo),那么它不會(huì)斷開(kāi)表單上各控件的數(shù)據(jù)綁定。
需要注意的是返回光標(biāo)字段名與Load事件里打開(kāi)的光標(biāo)的字段名應(yīng)該是相同的。
四、將新增、修改、刪除記錄寫(xiě)回到SQL?Server數(shù)據(jù)庫(kù)
前面講過(guò)SQL Server是一個(gè)簡(jiǎn)單的機(jī)制,常用的就是4條命令:Insert、Select、Update、Delete。
那么我們?cè)趺从肧PT將我們的數(shù)據(jù)變化寫(xiě)回到SQL Server數(shù)據(jù)庫(kù)?
我們可以構(gòu)造Insert、Update、Delete語(yǔ)句來(lái)發(fā)送數(shù)據(jù)到SQL Server。Update、Delete語(yǔ)句必須包含一個(gè)或多個(gè)關(guān)鍵字段以唯一地標(biāo)識(shí)需要更新或刪除的記錄。沿用前面建立SPT連接的句柄Handle:
1.新增數(shù)據(jù)
StrCmd_1 = [INSERT INTO authors (au_id, au_lname, au_fname, phone, address,;
city,state,zip,contract) VALUES ('999-99-9999', 'White', 'Johnson', )
StrCmd_2 = ['408 496-7223','Bigge Rd', 'Menlo Park', 'CA','31002', '1')]
lr = SQLExec ( Handle, StrCmd_1+ StrCmd_2)
IF lr<0
Msg = [新增數(shù)據(jù)失敗!]
MESSAGEBOX( Msg, 64, _VFP.Caption )
ENDIF
值得注意的是:這里要遵守對(duì)該表數(shù)據(jù)的約束,要不然,總會(huì)以失敗告終。
2.修改數(shù)據(jù)
StrCmd = [UPDATE authors SET phone = '999 496-7223', address = '2036 shiqiaoyjl' ;
WHERE (au_id = '999-99-9999') AND (au_lname = 'White')]
lr = SQLExec ( Handle, StrCmd )
IF lr<0
Msg = [修改數(shù)據(jù)失敗!]
MESSAGEBOX( Msg, 64, _VFP.Caption )
ENDIF
3.刪除數(shù)據(jù)
StrCmd = [delete authors WHERE (au_id = '999-99-9999') AND (au_lname = 'White')]
lr = SQLExec ( Handle, StrCmd )
IF lr<0
Msg = [刪除數(shù)據(jù)失敗!]
MESSAGEBOX( Msg, 64, _VFP.Caption )
ENDIF
五、經(jīng)驗(yàn)之談
1.用SPT方式可以很好的使用事物處理
也許我們記憶憂新,在使用DBF表時(shí),是用開(kāi)放式行緩沖方式,然后發(fā)出TableUpdate(.T.)以永久地修改數(shù)據(jù),或者發(fā)出TableRevert(.T.)來(lái)忽略數(shù)據(jù)更改的。還有在用遠(yuǎn)程視圖方式整合SQL Server開(kāi)發(fā)時(shí),用的也是緩沖的機(jī)制。這種機(jī)制猶如黑匣子,我們控制不了其操作過(guò)程。用SPT方式就不一樣,用這種方式,我們可以想回滾到哪里就回滾到哪里。
2.保留選項(xiàng)表的本地備份
可以復(fù)制部分SQLSerever表為DBF表到本地應(yīng)用程序目錄。你也許會(huì)感到奇怪,我用了SQLSerever表,為什么還要用DBF表?原因很簡(jiǎn)單,是因?yàn)樾阅堋BF表小而巧的特性,對(duì)數(shù)據(jù)量少,單用戶獨(dú)占使用的環(huán)境下有其無(wú)可比擬的性能優(yōu)勢(shì)。
我們的很多表單會(huì)有組合框或者列表框,這些組合框和列表框顯示的數(shù)據(jù)源大多來(lái)自小的數(shù)據(jù)表,而且這些數(shù)據(jù)不是經(jīng)常改變的。那就沒(méi)必要在每次實(shí)例化表單時(shí)為每一個(gè)小表都連接到SQLServer。取而代之的是,可以以DBF表的方式為這些表在本地保留完整的備份,只在服務(wù)器表數(shù)據(jù)改變時(shí)再刷新它。
參考文獻(xiàn)
[1]《在VFP里操作和管理SQL?SERVER(介紹SQL-DMO) 》,作者:buffer,下載地址:http://www.myf1.net/bbs/dispbbs.asp boardID=1&replyID=189716
&ID=180379&skin=1
[2]《FoxPro開(kāi)發(fā)者學(xué)SQL》,作者:婁山關(guān).下載地址:http://www.myf1.net/bbs/dispbbs.asp?boardID=1&replyID=217870&ID=238414&skin=1
[3]《SQL SERVER 起步》,作者:陳純.下載地址:http://www.vfp.cn/article_
view.asp id=493