小氣的神 2001-10-11
接著上一篇所說的三個過程中第一個步驟開始進行,環境需要兩部機器,一部做SQL Server,一部做App和安裝IIS。類比現在常見的Windows DNA結構,在ASP中調用Biz組件。VB的Client端我就省略了,選擇IE作為Client端,唯一想驗證的是構架和組件是OK的就好了。
這一篇和dotNET還沒有任何關係,因為那時還沒有dotNET技術,為了更真實的類比現實比如複雜一點帶有事務要求的邏輯,我決定把SQL Server和組件放在兩台機器上。
內容我選用SQL Server內建的Pub資料庫的Author表作為原型。當我翻看原來的一些應用代碼和組件發現整個的代碼一般分為兩類:一類是完成一個商業和商務邏輯的操作,帶入必須的參數給Biz組件,Biz組件調用其它Biz組件或DB組件完成需要的各種操作,然後返回一個簡單的資料類型回來給表現層。比如一個String字串(錯誤描述),一個Long型(表示某種流水號,什麼編號或是錯誤碼等);另一類是查詢或某種操作之後返回的大量資料,讓我慶幸的是自己已經習慣了用ADODB.Recordset來返回這些大量資料,所以這一類很統一,一般都是ADODB.Recordset類型的傳回值。除此之外連Variant都很少很少,自己定義的結構類型在Biz這一層的傳回值中幾乎為零。
對於WebService來說,資料被統一成XML的格式,我開始想象這些ADODB.Recordset在XML中會是什麼模樣的?用戶端又如何使用這些XML格式的ADO資料呢?幾乎第一個反應是用Microsoft SOAP Toolkit來解決這個問題,所以對SOAP Toolkit產生的WSDL檔案充滿好奇,想知道這種ADODB.Recordset傳回值的WSDL會是怎樣的。事實上,以後實驗的結果讓人泄氣。不過問題更早的暴露出來了,就是這些自訂或說不是SOAP支援的資料類型的資料如何處理的問題,目前集中在ADODB.Recorset這種資料類型上。這些問題也就決定了要產生的db和Biz組件。
DB組件沒有特別的,Biz組件我決定直接調用這些DB組件,先沒有任何的邏輯,事實上Biz中可能是很複雜的,調用很多其它的Biz或DB組件,但往往它最後只會有一個結果:成功或失敗,或是返回一組資料,也就是我上面歸類的兩種。所以我開始用類似的Update,Delete功能:
Public Function DeleteAuthor(ByVal au_id As String) As Long
來類比第一類返回SOAP支援的單一資料類型的情況,現實的應用中可能會是:
Public Function ChangePaymentType( Byval nTypeID as Long, Byval Value as Integer) As Long 一個修改使用者付款條件的商業邏輯。
用Select 功能
Public Function GetAuthorsByName(ByVal fName As String, ByVal lName As String) As ADODB.Recordset 來類比第二類返回不是基礎資料型別 (Elementary Data Type)的傳回值,現實的應用中可能會是
Public Function GetCustomerInfoByID( Byval nCustomerID as Long ) As ADODB.Recordset 一個根據客戶ID來獲得客戶資料的商業邏輯。
我列出後面用的最多的兩個函數的代碼,特別是這兩個函數名會在後面被大量涉及到:
Biz組件:bus_Authors.Authors ,編譯成DLL: bus_Authors.DLL
Public Function Version() As String
Version = "VB & SOAP ver 1.00 "
objCtx.SetComplete
End Function
Public Function GetAuthors() As ADODB.Recordset
On Error GoTo ErrHandler
Dim obj As Object
Set obj = CreateObject(dbcomName)
Set GetAuthors = obj.GetAuthors()
objCtx.SetComplete
Exit_Err:
Exit Function
ErrHandler:
Set GetAuthors = Nothing
objCtx.SetAbort
Err.Raise Err.Number, SetErrSource(modName, "GetAuthors"), Err.Description
Resume Exit_Err
End Function
db組件:db_Authors.Authors ,編譯成DLL: db_Authors.DLL
Public Function GetAuthors() As ADODB.Recordset
On Error GoTo HandleError
Dim Rst As ADODB.Recordset
Dim strSql As String
Set Rst = newClientRstOnlyRead(5)
strSql = " SELECT * FROM Authors "
Rst.Open strSql, strConstruct, adOpenStatic, adLockReadOnly, adCmdText
If Not IsRstEmpty(Rst) Then
Set GetAuthors = Rst
Else
Set GetAuthors = Nothing
End If
objCtx.SetComplete
HandleExit:
Exit Function
HandleError:
objCtx.SetAbort
Set GetAuthors = Nothing
Err.Raise Err.Number, SetErrSource(modName, "GetAuthors"), Err.Description
Resume HandleExit
End Function
Version()和GetAuthors()分別用來類比上訴的兩類傳回值的情況,剩下的還包括下面的函數:
Public Function Echo(ByVal sEcho As String) As String
Public Function GetAuthorsByName(ByVal fName As String, ByVal lName As String) As ADODB.Recordset
Public Function DeleteAuthor(ByVal au_id As String) As Long
Public Function UpdateAuthorByAddress(ByVal au_id As String, ByVal sAddress As String) As Long
這些不同的是加入了參數,和上面的Version和GetAuthors傳回值沒有什麼不同所以我後面只討論Version和GetAuthors這兩個函數,剩下的實現上只有稍稍不同。
完成後編譯組件,安裝在Windows 2000的COM +中,我建立了一個叫Authors的Application。然後利用Component Services分別將Authors Application用Export...功能倒出一個Server Application 和Application proxy的安裝包,後面我們會用上它們。如圖:
然後設定好IIS,建立一個虛擬目錄Authors寫一個簡單的ASP頁面調用bus_Authros.Authors組件的Version和GetAuthors方法產生一個Html的輸出(VB和ASP的用戶端的測試代碼我都省略了)。保證Http://localhost/Authors/TestAuthors.asp 或
Http://henrysvr/Authors/TestAuthors.asp 調用正常在IE中產生頁面輸出。
TestAuthors.asp放的物理的目錄我假設是:C:\Inetpub\wwwroot\Authors中,這個目錄在下面的章節中還會涉及到並且存放我們的WSDL等檔案。
如果上述一切OK那麼基本上完成了第一步,有了一個簡單的Windows DNA構架的例子使得下面的步驟可以開始進行,目前的構架可能象下面這樣的:
另外防火牆都將不再考慮在內了,我沒有類比它。實際應用中防火牆是需要具體考慮的一個因素。