重新整理緩衝(refreshing buffers)
記得在“以緩衝理解更新衝突”一節中我們提到過什麼情況下Visual FoxPro會重新整理緩衝區。其中“遠程視圖游標被開啟”是很好的理解,這裡不再累述。
以 REQUERY()函數重新整理遠程視圖游標
REQUERY()函數的作用就是重新執行遠程視圖的SELECT-SQL描述,也就是重新開啟遠程視圖游標,所以對系統造成較大的負擔。對於這個函數,我有幾點建議:
-
執行成功,返回:1;反之,函數返回:0。
-
執行成功,記錄指標將停在首記錄,因為本函數就如同重新開啟遠程視圖。
-
由於是重新下載資料,本函數對緩衝進行全部重新整理。
-
行緩衝下,如果修改了一行記錄,但未發送更新時,使用本函數,Visual FoxPro將先發送更新,如果沒有更新衝突,才重新下載資料游標;如果發生更新衝突,本函數不被執行,返回 0。
-
表緩衝下,如果修改了任何記錄,但沒有發送更新,本函數將不被執行,出現如圖11的提示,返回0。
圖 11。 表緩衝下更新沒有被確認,不能使用REQUERY()函數
發送更新成功,只重新整理被更新記錄的相關欄位的緩衝
也許這個標題很難理解,那麼我們就分析一下:
-
無論是行緩衝還是表緩衝模式,發送更新成功,Visual FoxPro將已更新欄位的新值填入緩衝。也就是說,沒有被更新欄位的緩衝區不被重新整理。
-
行緩衝下發送更新成功,只重新整理目前記錄地被更新欄位的緩衝。
-
表緩衝下發送更新成功,只重新整理被更新的若干記錄的各自被更新欄位的緩衝。
我認為,Visual FoxPro所謂重新整理緩衝,只不過是Visual FoxPro自己的行為而與遠端資料源無關,也就是由Visual FoxPro產生UPDATE-SQL語句時,Visual FoxPro自動將新值填入緩衝,Visual FoxPro再發送此SQL描述。所以被重新整理的就是被更新的欄位的緩衝,並且無論更新是否成功!
遠程視圖的其他屬性
遠程視圖的進階屬性可以通過可視工具設定,下面我們就講解一下:
FetchASNeed 和 FetchSize 即:取得遠端所需的資料和每次提取的記錄數
這兩個屬性是成對工作的,預設設定是:
DBSETPROP("ViewName","View","FetchSize",100)
DBSETPROP("ViewName","View","FetchAsNeed",.F.)
表示遠程視圖開啟時,每批下載100條記錄,當第一批100條記錄被下載完畢後,Visual FoxPro將把控制權還給使用者或繼續往下執行程式。這樣就有問題了:如果幾個遠程視圖共用一條串連,接可能造成串連堵塞。如下:
CREATE SQL VIEW VOrders ;
REMOTE CONNECTION Northwind SHARE;
AS SELECT * FROM Orders
CREATE SQL VIEW VCustomers ;
REMOTE CONNECTION Northwind SHARE;
AS SELECT * FROM Customers
*在命令視窗同時選中以下命令,按斷行符號鍵
Use VOrders in 0
Use VCustomers in 0
*彈出“串連 Northwind忙" 的提示視窗
讓我們分析原因:當VOrder的一批100條記錄被下載完畢後,Visual FoxPro就執行開啟VCustomers表的命令,這時對於串連Northwind將面臨兩項任務:繼續下載VOrder的第二批100條記錄、下載VCustomers的第一批記錄,一個串連無法同時應付兩項任務,所以“串連忙”。
解決以上問題,可以這樣設定:
DBSETPROP("VOrders","View","FetchSize",-1)
*表示一次下載所有記錄,完成此任務才將控制權交回或繼續執行程式。
如果你這樣設定:
DBSETPROP('VOrders',"View","FetchSize",100)
DBSETPROP("VOrders","View","FetchAsNeed",.T.)
USE VOrders
*下在100條記錄,並將控制權交還使用者,由於FetchAsNeed=.T.,不像剛才——Visual FoxPro自動控制繼續下載資料,串連被霸佔
go 100
*第100條記錄已經下載,所以VOrders不下載任何資料,串連被霸佔
go 105
*第105條記錄還沒有下載到用戶端,所以VOrder下載5條資料以滿足使用者的需要,串連被霸佔
go bottom
*下載所有記錄,串連被釋放
MaxRecords 即:要提取的最大記錄數
這個屬性是指遠程視圖游標最多可以下載的記錄數,並且它的優先順序比上兩個屬性高。也就是說無論上兩個屬性怎樣設定,用戶端就只能擁有小於等於MaxRecords條從遠端下載的記錄,並且達到這個數量後,“霸佔”串連就被釋放、可以供其它視圖使用。這個屬性可以這樣設定:
DBSETPROP("ViewName", "View", "MaxRecords", 25)
FetchMemo 即:取備忘欄位
如果遠程視圖中包含備忘欄位,一般認為:一次性下載這些資料到用戶端是很沒有意義的、也是沒有效率的,而且猛增了網路流量。比較好的做法是:用的時候才下載。所謂用的時候就是指:明顯或隱含的Modi Memo命令。可以這樣設定它的屬性:
DBSETPROP("ViewName", "view", "FetchMemo", .F.)
CompareMemo 即:在 Where 子句中包含備忘欄位
當遠程視圖包含備忘欄位或是通用欄位時,這個屬性非常重要的。這個屬性的預設值是.T.,即在檢測更新衝突時把這兩種欄位與其它類型的欄位同等看待。筆者認為,這種設定有一個不合理、一個錯誤,請聽我道來:
先說錯誤,當一個通用型(不包括“備忘型欄位”)欄位被設定為可更新,並使用了“關鍵字與可更新欄位”或“關鍵字與已更新欄位”的更新衝突檢測方式,Visual FoxPro 不允許這種設定。在視圖設計階段,Visual FoxPro 不會指出這個錯誤,但當實際發送 UPDATE-SQL 時會出現錯誤提示。
在講“不合理”。我剛才指出,備忘欄位是可以參與更新衝突檢測的,但是這樣對伺服器的壓力很大、對網路的壓力也很大。
所以一般應用中,我們會把該值設定為 .F.,即當更新衝突檢測方式為“關鍵字與可更新欄位”或“關鍵字與已更新欄位”的時候,即使有關備忘欄位或通用型欄位用戶端程式被更改,Visual FoxPro 發送 UPDATE-SQL 會把這兩類欄位從 Where 子句中挖去。這樣可以避免以上我提出的“一個錯誤、一個不合理”。
可以這樣設定:
DBSetProp('VEMPLOYEES', 'View', 'CompareMemo', .F.)
欄位屬性
DefaultValue
如果您希望對遠程視圖執行Append命令時,系統自動填列有關欄位,那麼就有必要設定該屬性:
DBSETPROP("myview.myfield", "field", "DefaultValue", ".T. ")
DBSETPROP("myview.myfield", "field", "DefaultValue", "'Bob'")
DBSETPROP("myview.myfield", "field", "DefaultValue", Date())
DataType
以下是Visual FoxPro欄位類型與SQL Server欄位類型的比較:
| SQL type |
Visual FoxPro type |
| binary, varbinary |
Memo |
| bit |
Logical |
| char, varchar |
Character |
| datetime, smalldatetime |
Datetime |
| decimal |
Numeric |
| float |
Double |
| image |
General |
| int, smallint, tinyint |
Integer |
| money, smallmoney |
Currency |
| numeric |
Numeric |
| sysname |
Character |
| text |
Memo |
| timestamp |
Memo |
您可以這樣設定:
DBSETPROP("Vemployees.birthdate", "field", "DataType", "D")
UpdateName
這個屬性在多表串連是很重要,在多個表中許多列可能有相同的名稱,所以必須明確的告訴遠程視圖,視圖中的列與資料來源表的列的對應關係。如:
DBSETPROP("VCustomers.postalcode", "field", "UpdateName", "customers.postalcode")