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