應(yīng)用程序開(kāi)發(fā)的一個(gè)偉大的事實(shí)是:對(duì)于每一件事情都可用多種方法來(lái)完成.建造應(yīng)用程序時(shí)的最困難的事情是選擇一種方法及確定它是否比其它的方法更好. 在客戶服務(wù)器開(kāi)發(fā)中,這種情況是你是在用兩種數(shù)據(jù)庫(kù)引擎進(jìn)行處理, Visual FoxPro 在前端而一個(gè)強(qiáng)有力的 SQL 數(shù)據(jù)庫(kù)引擎在后端.
《整合 SQL Server 和 Visual FoxPro》一文探索了用 SQL pass-through. 創(chuàng)建兩層客戶服務(wù)器程序. 在本文中,用Visual FoxPro建立一個(gè) OLE 服務(wù)器用于創(chuàng)建三層客戶服務(wù)器程序. 添加一個(gè)中間層,給你以額外的地方來(lái)放置代碼和執(zhí)行驗(yàn)證.
胖客戶問(wèn)題
客戶服務(wù)器應(yīng)用程序開(kāi)發(fā)者如何分離地處理前端和后端的困境是眾所周知的. Visual FoxPro 和 SQL Server 兩者都具有非常有力的數(shù)據(jù)庫(kù)引擎. 兩者都有有力的編程語(yǔ)言并有能力驗(yàn)證數(shù)據(jù)和強(qiáng)制商業(yè)規(guī)則.
近來(lái)有很多關(guān)于工業(yè)上的胖客戶和瘦客戶以及它們對(duì)客戶服務(wù)器應(yīng)用程序開(kāi)發(fā)的影響. 作為可用的前端開(kāi)發(fā)工具已發(fā)展成熟,并有越來(lái)越依賴它們的傾向. 后端的負(fù)擔(dān)并不輕,但也會(huì)造成問(wèn)題.
載入前端的第一個(gè)問(wèn)題是需要一個(gè)更為有力的計(jì)算機(jī). 當(dāng)然如果你使用 Visual FoxPro 作為后端你可能需要至少 486 和 12 MB 內(nèi)存. 這個(gè)問(wèn)題是術(shù)語(yǔ)"胖客戶"是如何產(chǎn)生的. 如果你正在選擇要使用的后端,前端是當(dāng)然要考慮的. 你會(huì)權(quán)衡 Visual FoxPro, Visual Basic, Access, Delphi, PowerBuilder, Java 以及其它所有編程語(yǔ)言的優(yōu)缺點(diǎn)和資源需求. Java 是動(dòng)人的,因?yàn)樗峁┱嬲膿碛凶銐蚰芰Φ氖菘蛻羟岸顺兄Z. Visual FoxPro 5.0 值得注目地比 3.0 減肥.
前端執(zhí)行大量處理的第二個(gè)問(wèn)題是假如你的驗(yàn)證和商業(yè)規(guī)則發(fā)生變化你必須修改在前后中的代碼. 這可能是或不是一個(gè)問(wèn)題. 假設(shè)你正在開(kāi)發(fā) Visual FoxPro 前端, 你也要發(fā)生對(duì) SQL Server 后端的修改. 如果你是驗(yàn)證和商業(yè)規(guī)則代碼的編寫(xiě)者, 你大概會(huì)只寫(xiě)一次, 用 Visual FoxPro 或 SQL Server 儲(chǔ)存過(guò)程或兩者的組合. 如果某些方法必須修改,而你是修改者, 很大的問(wèn)題的代碼位于什么地方?
在另一方面, 你可能編寫(xiě)前端而不寫(xiě)后端. 你可能不被允許編寫(xiě)你自己的 Select, Insert, Update 和Delete. 后端管理人可能限制你只能使用儲(chǔ)存過(guò)程. 這種方法的好處是保證前端的正確執(zhí)行. 如果只允許你通過(guò)儲(chǔ)存過(guò)程訪問(wèn)數(shù)據(jù), 你將被迫按正確的順序執(zhí)行. 例如, 如果你刪除一個(gè)成員則不能忘記刪除該成員的預(yù)約. 如果你添加一個(gè)新成員則不能忘記放入新的 ID 到 Adult 表中.
如果你的前端只是一系列訪問(wèn)相同后端的前端的一個(gè)又會(huì)怎么樣呢? 在這種情況下你會(huì)想要所有邏輯在后端上發(fā)生. 那種方法, 如果要進(jìn)行任何修改,只需要修改一個(gè)地方.
三層體系
客戶服務(wù)器開(kāi)發(fā)最近的一個(gè)進(jìn)步是三層體系方案. 傳統(tǒng)的客戶服務(wù)器是兩層的, 由一個(gè)客戶和一個(gè)服務(wù)器組成. 正如上面的討論,如果太多的處理集中在客戶或服務(wù)器上, 可能會(huì)有潛在的問(wèn)題. 三層體系引入一個(gè)中間層, 用于減輕兩端的負(fù)擔(dān).
在一個(gè)典型的三層體系中, 如下表所示, 各層負(fù)責(zé)提供一個(gè)服務(wù). 客戶提供用戶服務(wù), 它主要由用戶界面組成. 服務(wù)器提供數(shù)據(jù)服務(wù), 由數(shù)據(jù)和維護(hù)訪問(wèn)方法組成. 中間層提供商業(yè)服務(wù), 由數(shù)據(jù)驗(yàn)證和強(qiáng)制商業(yè)方法組成
表1: 分層應(yīng)用程序體系
要充分認(rèn)識(shí)到該結(jié)構(gòu)的潛力, 你應(yīng)該使中間層易于訪問(wèn)多個(gè)前端. 如果它強(qiáng)制你規(guī)則,則所有客戶需要與它交談. 不管客戶是用 Visual FoxPro,Visual Basic 還是其它語(yǔ)言寫(xiě)成,這都是事實(shí).
中間層將會(huì)運(yùn)行于不同的機(jī)器上. 這允許它可被多個(gè)客戶訪問(wèn),而且它提供性能. 記住, 胖客戶問(wèn)題是客戶機(jī)器負(fù)擔(dān)過(guò)重. 在一個(gè)兩層結(jié)構(gòu)中你可能必須為每一個(gè)客戶提供 16 MB (功更多) 內(nèi)存的 Pentium 機(jī)器. 在一個(gè)三層結(jié)構(gòu)中你可以將中間層放在一個(gè) 32 MB 雙處理器 Pentium 機(jī)器,并愉快地在 12 MB 內(nèi)存的486 機(jī)器上運(yùn)行客戶程序.
至少可以用兩種方法來(lái)設(shè)置中間層. 一種方法是用一個(gè) SQL Server 機(jī)器作為服務(wù)器和中間層. 本文中使用的方法是使用一個(gè)在 Visual FoxPro 中創(chuàng)建的 OLE server 作為中間層. OLE server 從 Visual FoxPro 中調(diào)用, 或?qū)τ谌魏?OLE 控制器, 使用 CreateObject() 函數(shù), 與你調(diào)用 Excel 或 Word 作為 OLE Automation 服務(wù)器一樣.
創(chuàng)建Visual FoxPro OLE 服務(wù)程序
如果你還不知道如何在 Visual FoxPro 中創(chuàng)建一個(gè) OLE 服務(wù)器請(qǐng)參閱《Visual FoxPro 作為 OLE Automation Servers》 和《自定義 OLE Servers》. 你也可以從 Visual FoxPro 聯(lián)機(jī)幫助文檔中 (Visual FoxPro 開(kāi)發(fā)指南第十六章)知道如何做.
在 Win32 的世界中, OLE 服務(wù)器可以作為 InProc 或 OutOfProc 服務(wù)器創(chuàng)建(Windows 95 和 Windows NT) ,它是一個(gè)運(yùn)行應(yīng)用程序的處理并可以尋址到 4 GB 的內(nèi)存, 一半是用于保存處理代碼,另一半是系統(tǒng)使用. InProc 服務(wù)器是編譯成 DLL 并運(yùn)行在調(diào)用它的過(guò)程的相同的地址空間. OutOfProc 服務(wù)器是編譯成 EXE 文件并作為單獨(dú)的過(guò)程運(yùn)行. InProc 服務(wù)器可提供司長(zhǎng)能,因?yàn)檫^(guò)程中通信比內(nèi)部通信慢. 在另一方面, 由于 OutOfProc 服務(wù)器運(yùn)行在一個(gè)單獨(dú)的過(guò)程中,你可以利用多處理器的優(yōu)勢(shì).
OLE 服務(wù)器也可在本地或遠(yuǎn)程運(yùn)行. 典型地一個(gè)遠(yuǎn)程 OLE 服務(wù)器是一個(gè) OutOfProc 服務(wù)器并位于超級(jí)計(jì)算機(jī)上. 這允許任意多個(gè)客戶機(jī)器訪問(wèn)它. Remote Automation Connection Manager 可用于配置服務(wù)器和客戶機(jī)器來(lái)允許遠(yuǎn)程自動(dòng)控制.
示例數(shù)據(jù)
本文使用的示例數(shù)據(jù)是來(lái)自于 SQL Server 6.5 的圖書(shū)館應(yīng)用程序. 圖書(shū)館應(yīng)用程序想要保持對(duì)其成員、圖書(shū)和借閱的跟蹤.
表結(jié)構(gòu)
圖書(shū)館應(yīng)用程序中的主要表之一是 Member 表, 圖書(shū)館中的每一位成員在其中有一條記錄. 這里一個(gè)有趣的手法是少年必須要有成年人擔(dān)保才能成為圖書(shū)館成員. 大概由于少年會(huì)在相同的地方成長(zhǎng)為成年人, 因此有兩個(gè)單獨(dú)的表 Adult(成年) 和 Juvenile(少年). 這樣節(jié)約了磁盤(pán)空間,因?yàn)橐坏阒懒顺扇说牡刂穭t所有少年的地址信息是多余的. 另外, 少年的期滿日期與成人相同. 進(jìn)一步說(shuō), 你不用在意成人的出生日期,你只需注意少年的出生日期及何時(shí)滿18 歲變?yōu)槌扇?至少在表中要反映出來(lái)!).
以下代碼顯示了用于創(chuàng)建 Member, Adult 和 Juvenile 表的SQL Server 語(yǔ)句:
CREATE TABLE member
( member_no member_no NOT NULL identity(1,1),
lastname shortstring NOT NULL ,
firstname shortstring NOT NULL ,
middleinitial letter NULL ,
photograph IMAGE NULL )
CREATE TABLE adult
( member_no member_no NOT NULL ,
street shortstring NOT NULL ,
city shortstring NOT NULL ,
state statecode NOT NULL ,
zip zipcode NOT NULL ,
phone_no phonenumber NULL ,
expr_date DATETIME NOT NULL )
CREATE TABLE juvenile
( member_no member_no NOT NULL ,
adult_member_no member_no NOT NULL ,
birth_date DATETIME NOT NULL )
Member 表中的 member_no 字段在添加新記錄時(shí)會(huì)由 SQL Server 自動(dòng)生成。該字段是一個(gè) Identity 列。起始值為 1 ,增量值也是 1。這樣在表中輸入的第一條記錄的 member_no 值就是 1。對(duì)于后來(lái)插入到表中的記錄 member_no 的值自動(dòng)增加 1。當(dāng)添加一條記錄時(shí)如果客戶沒(méi)有指定 member_no 的值。SQL Server 自動(dòng)維護(hù)它并詢問(wèn)客戶使用什么值。
在 Adult 和 Juvenile 表中的 member_no 不是 Identity 列。這些記錄中的值必須與 Member 表中相應(yīng)的 member_no 值相匹配。當(dāng)新記錄添加到圖書(shū)館庫(kù)時(shí),一個(gè)記錄首先會(huì)添加到 Member 表中。SQL Server 的全局變量 @@Identity 包含了自動(dòng)生成的 member_no。然后添加到 Adult 或 Juvenile 表中的記錄的 member_no 值將使用 @@Identity 中的值。
定義參照完整性
在早期版本的 SQL Server 參照完整性是通過(guò)使用觸發(fā)器強(qiáng)制執(zhí)行,這與 Visual FoxPro 強(qiáng)制參照完整性相同。SQL Server 6.0 添加了可申明的參照完整性,這允許你定義你自己的作為數(shù)據(jù)結(jié)構(gòu)一部分的參照完整性規(guī)則。第一步是在各表中創(chuàng)建基本關(guān)鍵字約束,如以下代碼所示:
ALTER TABLE member
ADD constraint member_ident PRIMARY KEY clustered
(member_no)
ALTER TABLE adult
ADD constraint adult_ident PRIMARY KEY clustered
(member_no)
ALTER TABLE juvenile
ADD constraint juvenile_ident PRIMARY KEY clustered
(member_no)
基本關(guān)鍵字約束創(chuàng)建一個(gè)索引,用于強(qiáng)制 member_no 的性。在示例中創(chuàng)建一組索引用于對(duì)數(shù)據(jù)進(jìn)行物理排序。
定義可申明的參照完整性的第二步是在相關(guān)表之間創(chuàng)建外部關(guān)鍵字約束,如以下代碼所示:
ALTER TABLE adult
ADD CONSTRAINT adult_member_link FOREIGN KEY (member_no)
REFERENCES member (member_no)
ALTER TABLE juvenile
ADD CONSTRAINT juvenile_member_link FOREIGN KEY
(member_no) REFERENCES member (member_no)
ALTER TABLE juvenile
ADD CONSTRAINT juvenile_adult_link FOREIGN KEY
(adult_member_no) REFERENCES adult (member_no)
第一個(gè) Alter Table 定義了一個(gè) Member 和 Adult 表之間的關(guān)系。這是一個(gè)一對(duì)一關(guān)系,雖然這里沒(méi)有代碼指明或強(qiáng)制是這種類型的關(guān)系。第二個(gè) Alter Table 在 Member 和 Juvenile 表部定義了一個(gè)關(guān)系。最后一個(gè) Alter Table 在 Adult 和 Juvenile 表之間定義一個(gè)關(guān)系。這是一個(gè)一對(duì)多關(guān)系。
要意識(shí)到 SQL Server 當(dāng)前不支持級(jí)聯(lián)更新或刪除。如果你想那樣做就應(yīng)該用觸發(fā)器代替約束。
圖書(shū)館 OLE 服務(wù)程序使用 SQL pass-through 來(lái)與 SQL Server 圖書(shū)館數(shù)據(jù)庫(kù)交談. 服務(wù)器將包含采取行動(dòng)(如獲取一個(gè)成員的信息,添加一個(gè)新成員修改成員的信息和刪除一個(gè)成員)的方法. 服務(wù)器提供少量的屬性, 包括發(fā)生了何種錯(cuò)誤的屬性.
OLE 服務(wù)程序項(xiàng)目是 LIBRARYSERVER.PJX. 該項(xiàng)目包含一個(gè)自定義類叫做Members. 該類已被識(shí)別為OLE Public (要這樣做,在類信息對(duì)話框中復(fù)選適當(dāng)?shù)膹?fù)選項(xiàng)).
Members 類的成員和屬性, 分別在表1 和 表 2中列出.
方法 可視度 描述
InitConnection 公共 初始化與SQL Server 的連接
CloseConnection 公共 關(guān)閉與SQL Server 的連接
GetMember 公共 接收一個(gè)成員的信息
AddMember 公共 添加一個(gè)新成員
UpdateMember 公共 更新一個(gè)成員的信息
RemoveMember 公共 移除一個(gè)成員
SetError 受保護(hù) 保存 SQL Server 錯(cuò)誤
Convert 受保護(hù) 轉(zhuǎn)換值到串
表 2: 圖書(shū)館 OLE 服務(wù)程序?qū)傩?BR> 屬性 可視度 描述
NHandle 公共 連接句柄
NewID 公共 新添加的成員的ID
LastErrDesc 公共 最后出現(xiàn)的錯(cuò)誤的描述
在圖3顯示的項(xiàng)目信息對(duì)話框中, 項(xiàng)目的名稱為 VFPLibraryOLEServer. 結(jié)合類名 Members, 就產(chǎn)生了OLE 名稱 VFPLibraryOLEServer.Members. 這可以在注冊(cè)表的 HKEY_CLASSES_ROOT 中找到, 如圖4所示.
OLE 服務(wù)程序是在生成時(shí)自動(dòng)注冊(cè)到機(jī)器上. 如果你把它移動(dòng)到另一臺(tái)機(jī)器上可以用 REGSVR32.EXE 注冊(cè)它, REGSVR32.EXE 可以在 Windows 95 下的 System 目錄和 Windows NT 下的 System32 目錄中找到.
要在客戶應(yīng)用程序上使用 OLE 服務(wù)程序,應(yīng)使用下面這樣的代碼.
oLibrary = CreateObject("VFPLibraryOLEServer.Members")
當(dāng) Visual FoxPro 遇到該代碼時(shí)它首先檢查對(duì)象名是否是一個(gè) Visual FoxPro 類. 如果不是, 則檢查注冊(cè)表. 當(dāng)找到對(duì)象名和對(duì)象的標(biāo)識(shí)符 CLSID, is noted.
也是在注冊(cè)表的 HKEY_CLASSES_ROOT 中有一個(gè)名為 CLSID 的鍵值, 它包含一個(gè)所有具有 CLSID 的對(duì)象的入口. 就象你在圖5中看到的一樣, 注冊(cè)表保存著與可執(zhí)行文件相關(guān)的 CLSID. 這就是為什么當(dāng) Visual FoxPro 執(zhí)行它的 CreateObject 命令時(shí) Windows 知道如何啟動(dòng) OLE 服務(wù)程序.
使用圖書(shū)館 OLE 服務(wù)程序
表單 MEMBOLEFP.SCX 使用 Visual FoxPro 圖書(shū)館OLE 服務(wù)程序作為中間層來(lái)與 SQL Server 圖書(shū)館數(shù)據(jù)庫(kù)圖書(shū)館. 在調(diào)用服務(wù)程序后表單調(diào)用方法來(lái)獲取成員信息, 刪除和更新成員等.
《整合 SQL Server 和 Visual FoxPro》一文探索了用 SQL pass-through. 創(chuàng)建兩層客戶服務(wù)器程序. 在本文中,用Visual FoxPro建立一個(gè) OLE 服務(wù)器用于創(chuàng)建三層客戶服務(wù)器程序. 添加一個(gè)中間層,給你以額外的地方來(lái)放置代碼和執(zhí)行驗(yàn)證.
胖客戶問(wèn)題
客戶服務(wù)器應(yīng)用程序開(kāi)發(fā)者如何分離地處理前端和后端的困境是眾所周知的. Visual FoxPro 和 SQL Server 兩者都具有非常有力的數(shù)據(jù)庫(kù)引擎. 兩者都有有力的編程語(yǔ)言并有能力驗(yàn)證數(shù)據(jù)和強(qiáng)制商業(yè)規(guī)則.
近來(lái)有很多關(guān)于工業(yè)上的胖客戶和瘦客戶以及它們對(duì)客戶服務(wù)器應(yīng)用程序開(kāi)發(fā)的影響. 作為可用的前端開(kāi)發(fā)工具已發(fā)展成熟,并有越來(lái)越依賴它們的傾向. 后端的負(fù)擔(dān)并不輕,但也會(huì)造成問(wèn)題.
載入前端的第一個(gè)問(wèn)題是需要一個(gè)更為有力的計(jì)算機(jī). 當(dāng)然如果你使用 Visual FoxPro 作為后端你可能需要至少 486 和 12 MB 內(nèi)存. 這個(gè)問(wèn)題是術(shù)語(yǔ)"胖客戶"是如何產(chǎn)生的. 如果你正在選擇要使用的后端,前端是當(dāng)然要考慮的. 你會(huì)權(quán)衡 Visual FoxPro, Visual Basic, Access, Delphi, PowerBuilder, Java 以及其它所有編程語(yǔ)言的優(yōu)缺點(diǎn)和資源需求. Java 是動(dòng)人的,因?yàn)樗峁┱嬲膿碛凶銐蚰芰Φ氖菘蛻羟岸顺兄Z. Visual FoxPro 5.0 值得注目地比 3.0 減肥.
前端執(zhí)行大量處理的第二個(gè)問(wèn)題是假如你的驗(yàn)證和商業(yè)規(guī)則發(fā)生變化你必須修改在前后中的代碼. 這可能是或不是一個(gè)問(wèn)題. 假設(shè)你正在開(kāi)發(fā) Visual FoxPro 前端, 你也要發(fā)生對(duì) SQL Server 后端的修改. 如果你是驗(yàn)證和商業(yè)規(guī)則代碼的編寫(xiě)者, 你大概會(huì)只寫(xiě)一次, 用 Visual FoxPro 或 SQL Server 儲(chǔ)存過(guò)程或兩者的組合. 如果某些方法必須修改,而你是修改者, 很大的問(wèn)題的代碼位于什么地方?
在另一方面, 你可能編寫(xiě)前端而不寫(xiě)后端. 你可能不被允許編寫(xiě)你自己的 Select, Insert, Update 和Delete. 后端管理人可能限制你只能使用儲(chǔ)存過(guò)程. 這種方法的好處是保證前端的正確執(zhí)行. 如果只允許你通過(guò)儲(chǔ)存過(guò)程訪問(wèn)數(shù)據(jù), 你將被迫按正確的順序執(zhí)行. 例如, 如果你刪除一個(gè)成員則不能忘記刪除該成員的預(yù)約. 如果你添加一個(gè)新成員則不能忘記放入新的 ID 到 Adult 表中.
如果你的前端只是一系列訪問(wèn)相同后端的前端的一個(gè)又會(huì)怎么樣呢? 在這種情況下你會(huì)想要所有邏輯在后端上發(fā)生. 那種方法, 如果要進(jìn)行任何修改,只需要修改一個(gè)地方.
三層體系
客戶服務(wù)器開(kāi)發(fā)最近的一個(gè)進(jìn)步是三層體系方案. 傳統(tǒng)的客戶服務(wù)器是兩層的, 由一個(gè)客戶和一個(gè)服務(wù)器組成. 正如上面的討論,如果太多的處理集中在客戶或服務(wù)器上, 可能會(huì)有潛在的問(wèn)題. 三層體系引入一個(gè)中間層, 用于減輕兩端的負(fù)擔(dān).
在一個(gè)典型的三層體系中, 如下表所示, 各層負(fù)責(zé)提供一個(gè)服務(wù). 客戶提供用戶服務(wù), 它主要由用戶界面組成. 服務(wù)器提供數(shù)據(jù)服務(wù), 由數(shù)據(jù)和維護(hù)訪問(wèn)方法組成. 中間層提供商業(yè)服務(wù), 由數(shù)據(jù)驗(yàn)證和強(qiáng)制商業(yè)方法組成
表1: 分層應(yīng)用程序體系
要充分認(rèn)識(shí)到該結(jié)構(gòu)的潛力, 你應(yīng)該使中間層易于訪問(wèn)多個(gè)前端. 如果它強(qiáng)制你規(guī)則,則所有客戶需要與它交談. 不管客戶是用 Visual FoxPro,Visual Basic 還是其它語(yǔ)言寫(xiě)成,這都是事實(shí).
中間層將會(huì)運(yùn)行于不同的機(jī)器上. 這允許它可被多個(gè)客戶訪問(wèn),而且它提供性能. 記住, 胖客戶問(wèn)題是客戶機(jī)器負(fù)擔(dān)過(guò)重. 在一個(gè)兩層結(jié)構(gòu)中你可能必須為每一個(gè)客戶提供 16 MB (功更多) 內(nèi)存的 Pentium 機(jī)器. 在一個(gè)三層結(jié)構(gòu)中你可以將中間層放在一個(gè) 32 MB 雙處理器 Pentium 機(jī)器,并愉快地在 12 MB 內(nèi)存的486 機(jī)器上運(yùn)行客戶程序.
至少可以用兩種方法來(lái)設(shè)置中間層. 一種方法是用一個(gè) SQL Server 機(jī)器作為服務(wù)器和中間層. 本文中使用的方法是使用一個(gè)在 Visual FoxPro 中創(chuàng)建的 OLE server 作為中間層. OLE server 從 Visual FoxPro 中調(diào)用, 或?qū)τ谌魏?OLE 控制器, 使用 CreateObject() 函數(shù), 與你調(diào)用 Excel 或 Word 作為 OLE Automation 服務(wù)器一樣.
創(chuàng)建Visual FoxPro OLE 服務(wù)程序
如果你還不知道如何在 Visual FoxPro 中創(chuàng)建一個(gè) OLE 服務(wù)器請(qǐng)參閱《Visual FoxPro 作為 OLE Automation Servers》 和《自定義 OLE Servers》. 你也可以從 Visual FoxPro 聯(lián)機(jī)幫助文檔中 (Visual FoxPro 開(kāi)發(fā)指南第十六章)知道如何做.
在 Win32 的世界中, OLE 服務(wù)器可以作為 InProc 或 OutOfProc 服務(wù)器創(chuàng)建(Windows 95 和 Windows NT) ,它是一個(gè)運(yùn)行應(yīng)用程序的處理并可以尋址到 4 GB 的內(nèi)存, 一半是用于保存處理代碼,另一半是系統(tǒng)使用. InProc 服務(wù)器是編譯成 DLL 并運(yùn)行在調(diào)用它的過(guò)程的相同的地址空間. OutOfProc 服務(wù)器是編譯成 EXE 文件并作為單獨(dú)的過(guò)程運(yùn)行. InProc 服務(wù)器可提供司長(zhǎng)能,因?yàn)檫^(guò)程中通信比內(nèi)部通信慢. 在另一方面, 由于 OutOfProc 服務(wù)器運(yùn)行在一個(gè)單獨(dú)的過(guò)程中,你可以利用多處理器的優(yōu)勢(shì).
OLE 服務(wù)器也可在本地或遠(yuǎn)程運(yùn)行. 典型地一個(gè)遠(yuǎn)程 OLE 服務(wù)器是一個(gè) OutOfProc 服務(wù)器并位于超級(jí)計(jì)算機(jī)上. 這允許任意多個(gè)客戶機(jī)器訪問(wèn)它. Remote Automation Connection Manager 可用于配置服務(wù)器和客戶機(jī)器來(lái)允許遠(yuǎn)程自動(dòng)控制.
示例數(shù)據(jù)
本文使用的示例數(shù)據(jù)是來(lái)自于 SQL Server 6.5 的圖書(shū)館應(yīng)用程序. 圖書(shū)館應(yīng)用程序想要保持對(duì)其成員、圖書(shū)和借閱的跟蹤.
表結(jié)構(gòu)
圖書(shū)館應(yīng)用程序中的主要表之一是 Member 表, 圖書(shū)館中的每一位成員在其中有一條記錄. 這里一個(gè)有趣的手法是少年必須要有成年人擔(dān)保才能成為圖書(shū)館成員. 大概由于少年會(huì)在相同的地方成長(zhǎng)為成年人, 因此有兩個(gè)單獨(dú)的表 Adult(成年) 和 Juvenile(少年). 這樣節(jié)約了磁盤(pán)空間,因?yàn)橐坏阒懒顺扇说牡刂穭t所有少年的地址信息是多余的. 另外, 少年的期滿日期與成人相同. 進(jìn)一步說(shuō), 你不用在意成人的出生日期,你只需注意少年的出生日期及何時(shí)滿18 歲變?yōu)槌扇?至少在表中要反映出來(lái)!).
以下代碼顯示了用于創(chuàng)建 Member, Adult 和 Juvenile 表的SQL Server 語(yǔ)句:
CREATE TABLE member
( member_no member_no NOT NULL identity(1,1),
lastname shortstring NOT NULL ,
firstname shortstring NOT NULL ,
middleinitial letter NULL ,
photograph IMAGE NULL )
CREATE TABLE adult
( member_no member_no NOT NULL ,
street shortstring NOT NULL ,
city shortstring NOT NULL ,
state statecode NOT NULL ,
zip zipcode NOT NULL ,
phone_no phonenumber NULL ,
expr_date DATETIME NOT NULL )
CREATE TABLE juvenile
( member_no member_no NOT NULL ,
adult_member_no member_no NOT NULL ,
birth_date DATETIME NOT NULL )
Member 表中的 member_no 字段在添加新記錄時(shí)會(huì)由 SQL Server 自動(dòng)生成。該字段是一個(gè) Identity 列。起始值為 1 ,增量值也是 1。這樣在表中輸入的第一條記錄的 member_no 值就是 1。對(duì)于后來(lái)插入到表中的記錄 member_no 的值自動(dòng)增加 1。當(dāng)添加一條記錄時(shí)如果客戶沒(méi)有指定 member_no 的值。SQL Server 自動(dòng)維護(hù)它并詢問(wèn)客戶使用什么值。
在 Adult 和 Juvenile 表中的 member_no 不是 Identity 列。這些記錄中的值必須與 Member 表中相應(yīng)的 member_no 值相匹配。當(dāng)新記錄添加到圖書(shū)館庫(kù)時(shí),一個(gè)記錄首先會(huì)添加到 Member 表中。SQL Server 的全局變量 @@Identity 包含了自動(dòng)生成的 member_no。然后添加到 Adult 或 Juvenile 表中的記錄的 member_no 值將使用 @@Identity 中的值。
定義參照完整性
在早期版本的 SQL Server 參照完整性是通過(guò)使用觸發(fā)器強(qiáng)制執(zhí)行,這與 Visual FoxPro 強(qiáng)制參照完整性相同。SQL Server 6.0 添加了可申明的參照完整性,這允許你定義你自己的作為數(shù)據(jù)結(jié)構(gòu)一部分的參照完整性規(guī)則。第一步是在各表中創(chuàng)建基本關(guān)鍵字約束,如以下代碼所示:
ALTER TABLE member
ADD constraint member_ident PRIMARY KEY clustered
(member_no)
ALTER TABLE adult
ADD constraint adult_ident PRIMARY KEY clustered
(member_no)
ALTER TABLE juvenile
ADD constraint juvenile_ident PRIMARY KEY clustered
(member_no)
基本關(guān)鍵字約束創(chuàng)建一個(gè)索引,用于強(qiáng)制 member_no 的性。在示例中創(chuàng)建一組索引用于對(duì)數(shù)據(jù)進(jìn)行物理排序。
定義可申明的參照完整性的第二步是在相關(guān)表之間創(chuàng)建外部關(guān)鍵字約束,如以下代碼所示:
ALTER TABLE adult
ADD CONSTRAINT adult_member_link FOREIGN KEY (member_no)
REFERENCES member (member_no)
ALTER TABLE juvenile
ADD CONSTRAINT juvenile_member_link FOREIGN KEY
(member_no) REFERENCES member (member_no)
ALTER TABLE juvenile
ADD CONSTRAINT juvenile_adult_link FOREIGN KEY
(adult_member_no) REFERENCES adult (member_no)
第一個(gè) Alter Table 定義了一個(gè) Member 和 Adult 表之間的關(guān)系。這是一個(gè)一對(duì)一關(guān)系,雖然這里沒(méi)有代碼指明或強(qiáng)制是這種類型的關(guān)系。第二個(gè) Alter Table 在 Member 和 Juvenile 表部定義了一個(gè)關(guān)系。最后一個(gè) Alter Table 在 Adult 和 Juvenile 表之間定義一個(gè)關(guān)系。這是一個(gè)一對(duì)多關(guān)系。
要意識(shí)到 SQL Server 當(dāng)前不支持級(jí)聯(lián)更新或刪除。如果你想那樣做就應(yīng)該用觸發(fā)器代替約束。
圖書(shū)館 OLE 服務(wù)程序使用 SQL pass-through 來(lái)與 SQL Server 圖書(shū)館數(shù)據(jù)庫(kù)交談. 服務(wù)器將包含采取行動(dòng)(如獲取一個(gè)成員的信息,添加一個(gè)新成員修改成員的信息和刪除一個(gè)成員)的方法. 服務(wù)器提供少量的屬性, 包括發(fā)生了何種錯(cuò)誤的屬性.
OLE 服務(wù)程序項(xiàng)目是 LIBRARYSERVER.PJX. 該項(xiàng)目包含一個(gè)自定義類叫做Members. 該類已被識(shí)別為OLE Public (要這樣做,在類信息對(duì)話框中復(fù)選適當(dāng)?shù)膹?fù)選項(xiàng)).
Members 類的成員和屬性, 分別在表1 和 表 2中列出.
方法 可視度 描述
InitConnection 公共 初始化與SQL Server 的連接
CloseConnection 公共 關(guān)閉與SQL Server 的連接
GetMember 公共 接收一個(gè)成員的信息
AddMember 公共 添加一個(gè)新成員
UpdateMember 公共 更新一個(gè)成員的信息
RemoveMember 公共 移除一個(gè)成員
SetError 受保護(hù) 保存 SQL Server 錯(cuò)誤
Convert 受保護(hù) 轉(zhuǎn)換值到串
表 2: 圖書(shū)館 OLE 服務(wù)程序?qū)傩?BR> 屬性 可視度 描述
NHandle 公共 連接句柄
NewID 公共 新添加的成員的ID
LastErrDesc 公共 最后出現(xiàn)的錯(cuò)誤的描述
在圖3顯示的項(xiàng)目信息對(duì)話框中, 項(xiàng)目的名稱為 VFPLibraryOLEServer. 結(jié)合類名 Members, 就產(chǎn)生了OLE 名稱 VFPLibraryOLEServer.Members. 這可以在注冊(cè)表的 HKEY_CLASSES_ROOT 中找到, 如圖4所示.
OLE 服務(wù)程序是在生成時(shí)自動(dòng)注冊(cè)到機(jī)器上. 如果你把它移動(dòng)到另一臺(tái)機(jī)器上可以用 REGSVR32.EXE 注冊(cè)它, REGSVR32.EXE 可以在 Windows 95 下的 System 目錄和 Windows NT 下的 System32 目錄中找到.
要在客戶應(yīng)用程序上使用 OLE 服務(wù)程序,應(yīng)使用下面這樣的代碼.
oLibrary = CreateObject("VFPLibraryOLEServer.Members")
當(dāng) Visual FoxPro 遇到該代碼時(shí)它首先檢查對(duì)象名是否是一個(gè) Visual FoxPro 類. 如果不是, 則檢查注冊(cè)表. 當(dāng)找到對(duì)象名和對(duì)象的標(biāo)識(shí)符 CLSID, is noted.
也是在注冊(cè)表的 HKEY_CLASSES_ROOT 中有一個(gè)名為 CLSID 的鍵值, 它包含一個(gè)所有具有 CLSID 的對(duì)象的入口. 就象你在圖5中看到的一樣, 注冊(cè)表保存著與可執(zhí)行文件相關(guān)的 CLSID. 這就是為什么當(dāng) Visual FoxPro 執(zhí)行它的 CreateObject 命令時(shí) Windows 知道如何啟動(dòng) OLE 服務(wù)程序.
使用圖書(shū)館 OLE 服務(wù)程序
表單 MEMBOLEFP.SCX 使用 Visual FoxPro 圖書(shū)館OLE 服務(wù)程序作為中間層來(lái)與 SQL Server 圖書(shū)館數(shù)據(jù)庫(kù)圖書(shū)館. 在調(diào)用服務(wù)程序后表單調(diào)用方法來(lái)獲取成員信息, 刪除和更新成員等.