第8章 ADO基礎
在本書前7章中,已經講述了ASP的有關內容,以及ASP如何為Web站點帶來動態的內容。已經見到其腳本程序允許自定義Web頁面,使我們能夠構建功能更為強大的ASP頁面。
現在,將研究ASP和數據的集成。雖然對用於網頁中的腳本數量並無任何限制,但如果沒有某種形式的數據,很快就會進入一個死胡同。數據構成了Web站點的實際內容,或者指出了如何設置Web站點,因此總的說來數據是非常重要的。如果圍繞數據存儲建立Web站點,改變Web站點時只需要改變相應的數據即可。
ActiveX數據對象(ADO)是允許用戶與數據存儲進行交互的組件。這意味著只要基於某些數據就可建立一個網頁,或一種完全交互的電子商務系統。不論哪種方式,都是ADO使我們能與數據進行通信。我們將討論從數據存儲獲取和傳送數據的主要內容,以及得到數據後的數據處理方法。
首先研究什麼是ADO及其所包括的組件,然後討論如何訪問數據存儲。在下一章,將進一步學習ADO更先進的一些特性,如命令、存儲過程和優化應用程序的一些操作技巧。下一步研究Web服務器和浏覽器之間的交互過程,以及數據處理過程。然後研究數據存取領域中極具潛力的XML。XML是什麼?如何使用?因為XML代表著未來發展的一種趨勢,我們將介紹微軟關於通用數據存取的構想。在這個構想中,數據不只是從數據庫中獲得的。最後,看一下標准的微軟數據庫(如Access與SQL Server)以及在其中如何使用ADO。
本章從ADO開始,主要內容有:
· 研究ADO如何與數據進行交互。
· 了解ADO的組件。
· 如何與數據存儲連接和創建數據集。
· 如何處理和修改數據。
· 如何處理ADO錯誤。
8.1 ADO的定義
ADO是一個相當簡單的思想,一種讓你僅用一種方式去訪問數據的思想。ADO不算一個新思想,僅是采用現有的數據庫訪問技術,並將其融合而形成的一種適應現在和未來需要的新東西。適應未來的需求是一件十分重要的事。許多其他的技術,比如DAO和ODBC,在一些應用程序的開發過程中是可以接受的,然而隨著Internet的興起也出現了其自身的一些問題。
在許多情況下,傳統的數據存取方法看上去能解決一些關於兩層客戶/服務器系統的問題,但要求與數據之間要保持一種永久性的連接,並要提供強大的功能,比如快速響應的查詢、數據容易修改等。在Internet領域,現在必須考慮到Web無狀態性本質,和潛在的眾多可以訪問Web站點的用戶。要與數據建立永久的連接是不現實的,因此必須在設計應用程序時考慮這些因素。
那麼,OLD DB和ADO確切地講到底是什麼?讓我們與一些已有的數據存取技術做比較後再來回答這個問題。如果讀者曾經接觸過數據庫編程,或許比較熟悉ODBC和RDO。開放數據庫連接(ODBC)是允許訪問關系數據庫(比如Access和SQL Server)的應用程序編程接口(API)。正因為是一個API,許多程序員,特別是Visual Basic領域的程序員,發現它使用起來很復雜。遠程數據對象(RDO)是位於ODBC上層的ActiveX對象,可以提供ODBC的所有功能,並且使用起來比較簡單。
可以將OLE DB等同於ODBC,ADO等同於RDO。
OLE DB是應用程序與數據源交互的一種基本技術。
這相當復雜,確實也只有C和C++程序員能夠使用。正如ADO的名字所暗示的,它是易於訪問OLE DB功能的ActiveX對象。
你或許發現術語ActiveX與COM對象經常混用。對於ASP程序員來說它們並沒有本質上的區別,因為兩者都基於COM系統結構,只不過ActiveX是組件的一個跨平台標准,而COM是Windows專有的。
雖然微軟已經引入了一種新的存取數據的技術,但並沒有立即取消舊的技術,ODBC工作起來仍然很有效,並同OLE DB和ADO緊密地一起工作著。事實上,ODBC並不只是微軟的產品,也受到國際組件的控制。並且由於廣泛的使用,ODBC也不會突然消亡。隱藏在OLE DB背後的思想不是摒棄現有的技術,而是不斷地改進它們。
8.1.1 OLE DB和ADO的體系結構
前面已經給出了OLE DB與ADO在一些主要方面的簡要解釋。圖8-1顯示了這兩項技術與應用程序和數據存儲相互關系:
圖8-1 OLE DB、ADO與應用程序和數據存儲的關系
從圖8-1中可以看出整體思路。圖的頂端是應用程序(Web或常規的應用程序,這是無關緊要的),下面是提供對數據的訪問的ADO和/或OLE DB。ADO和OLE DB兩者兼有是因為OLE DB是一項基本技術。然而,OLE DB並不適用於所有語言,所以ADO位於OLE DB的上層,為那些不能直接訪問OLE DB的語言(如Visual Basic和腳本語言)提供編程接口。ADO提供了比OLE DB更容易的編程接口,因此即使那些可以直接使用OLE DB的編程語言,如C++或Java,也可使用ADO以簡化對數據的訪問。
圖8-1顯示的是微軟的編程語言,而ADO是一個COM組件,因此可用於任何與COM兼容的編程語言,比如Delphi或支持Active Scripting接口的腳本語言。所以,雖然ADO與平台有關,但與開發的語言是無關的。當然,對於ASP主要使用VBScript和JScript,在組件中使用ADO時,有一些Visual Basic代碼。
現在知道了OLE DB和ADO允許訪問數據,可是為什麼需要它們?老方法出問題了嗎?這裡有兩個主要原因:
首先,OLE DB和ADO是用來訪問數據存儲的。注意這裡指“數據存儲”而不是“數據庫”。盡管數據庫仍舊是數據存儲最為廣泛的形式,但並不一定含有全部的數據。一些消息系統,如Microsoft Exchange Server,也普遍地用於存儲數據。目錄服務(Directory Service)正開始在初露端倪,它們包含著有關用戶、機器等的數據;Web服務器中存有大量的信息。可以繼續羅列下去,很明顯需要一種能訪問所有這些不同類型數據的方法。
其次,源於Internet應用程序的興起與Web的狀態本質。過去的訪問數據的方法主要考慮與數據存儲保持永久連接的情況下處理數據。而OLE DB和ADO正是為解決這個問題而設計的,提供斷開連接的記錄集,我們將會在後面看到有關這方面的內容。
8.1.2 消費者與提供者
ADO系統結構圖展示了ADO是如何在應用程序和真實數據存儲之間發揮作用的。在微軟的文獻中,會看到兩個易懂的術語:消費者(Consumer)和提供者(PRovider),但搞清它們的確切定義至關重要。
提供者是提供數據的物體,消費者是使用(消耗)這些數據的物體。
在編程中,經常會發現應用程序是數據的消費者。但提供者呢?一般是數據存儲,並且由於OLE DB被設計成用於與不同的數據存儲對話,因此對於每一個獨特類型的數據存儲都有一個OLE DB提供者。
這種單獨提供者的思想並不新,但使編程變得容易了。編寫程序與ADO或OLE DB對話,OLE DB再與提供者對話。這意味著只需學會一套訪問數據的方法,無論數據如何存儲,在某些情況下確實可以完全不改變任何代碼而只更換提供者。這就是ADO和OLE DB真正優越的地方,為數據存儲提供了一套常用的編程接口。
要連接到數據存儲,必須使用OLE DB提供者。提供給ADO 2.5的初始設置為:
· Jet OLE DB 4.0:用於微軟Access數據庫。
· DTS Packages:用於SQL Server的數據轉換服務(Data Transformation Services)。
· Internet Publishing:用於訪問Web服務器。
· Indexing Services:用於索引目錄(Index Catalogs)。
· Site Server Search:用於站點服務器查找目錄。
· ODBC Drivers:用於ODBC數據源。
· OLAP Services:用於微軟OLAP服務器。
· Oracle:用於Oracle數據庫。
· SQL Server:用於微軟SQL Server數據庫。
· Simple Provider:用於簡單的文本文件。
· MSDataShape:用於層次數據。
· Microsoft Directory Services:用於Windows 2000的目錄服務。
· DTS Flat File:用於SQL Server的數據轉換服務的平面文件管理。
這只是微軟提供的初始列表,並取決於安裝在服務器上的服務及軟件。以Oracle數據提供者為例,要求在客戶機上安裝Oracle的客戶端軟件。
可以從別的制造商那裡獲得OLE DB提供者,用於其他數據存儲。甚至還可以編寫自己的提供者。在第11章,將演示如何編寫簡單的OLE DB提供者。
要想知道系統安裝了哪些提供者,可以使用Data Link propertIEs對話框。在本章後面,將介紹如何使用它。
8.1.3 提供者和驅動程序
值得注意的是,OLE DB對ODBC的兼容性,允許OLE DB訪問現有的ODBC數據源。其優點很明顯,由於ODBC相對OLE DB來說使用得更為普遍,因此可以獲得的ODBC驅動程序相應地要比OLE DB的要多。這樣不一定要得到OLE DB的驅動程序,就可以立即訪問原有的數據系統。
避免混淆提供者與驅動程序是重要的,圖8-2明確了它們之間的區別:
圖8-2 提供者與驅動程序之間的區別
提供者位於OLE DB層,而驅動程序位於ODBC層。如果想使用一個ODBC數據源,需要使用針對ODBC的OLE DB提供者,它會接著使用相應的ODBC驅動程序。如果不需要使用ODBC數據源,那麼可以使用相應的OLE DB提供者,這些通常稱為本地提供者(native provider)。
可以清楚地看出使用ODBC提供者意味著需要一個額外的層。因此,當訪問相同的數據時,針對ODBC的OLE DB提供者可能會比本地的OLE DB提供者的速度慢一些。
8.2 ADO 2.5對象模型
雖然在ADO 2.5對象模型中出現了兩個新對象,但與以前的版本基本上是類似的。圖8-3顯示了這些對象以及每個對象之間的關系:
圖8-3 對象之間的相互關系
如果以前使用過ADO,你會發現在這個新版本中出現了兩個新對象:Stream和Record對象。在第11、12章將詳細介紹它們。
Properties集合已經被有意地排除在圖8-3外,這樣你對幾個主要對象之間的交互關系就一目了然了。在本章的後面,有顯示PropertIEs集合的簡化對象模型。
讓我們更詳細地考察這幾個對象。
8.2.1 Connection對象
Connection對象是使我們能與數據存儲相連的對象。只有Connection對象才能指定希望使用的OLE DB提供者、連接到數據存儲的安全細節以及其他任何連接到數據存儲特有的細節。
應用注意的是,不必顯式創建一個Connection對象以連接到數據存儲。盡管確實需要指定連接細節,但沒有Connection對象,一樣可以創建Command、Recordset和Record對象。如果不創建自己的Connection對象,ADO將會隱含地為你創建一個Connection對象。如果要對提供者運行多條命令,應該顯式地創建一個Connection對象,這比每運行一條命令就創建一個連接更有效。
除了為數據存儲提供連接以外,Connection對象允許針對數據存儲執行命令操作。這些命令可以是結構化的或存儲的命令(例如,SQL命令或一個存儲過程),並且可以有選擇地從數據存儲中返回一些數據。
8.2.2 Command對象
Command對象是對數據存儲執行命令的對象。看到這裡讀者可能會產生疑問,Connection對象不也能這樣做嗎?是的,但是Connection對象在處理命令的功能上受到一定的限制,而Command對象是特別為處理命令的各方面問題而創建的。實際上,當從Connection對象中運行一條命令時,已經隱含地創建一個Command對象。
有時其他對象允許向命令傳入參數,但在Connection對象中不能指定參數的任何細節。使用Command對象允許指定參數(以及輸出參數和命令執行後的返回值)的精確細節(比如,數據類型和長度)。
因此,除了執行命令和得到一系列返回記錄,也可能得到一些由命令提供的附加信息。
對於那些不返回任何記錄的命令,如插入新數據或更新數據的SQL查詢,Command對象也是有用的。
8.2.3 Recordset對象
Recordset對象是ADO中使用最為普遍的對象,因為它含有從數據存儲中提取的數據集。我們經常運行不返回數據的命令,比如那些增加或更新數據的命令,但在大多數情況下很有可能會取得一系列記錄。
Recordset對象是擁有這些記錄的對象。可以更改(增加、更新和刪除)記錄集中的記錄,上下移動記錄,過濾記錄並只顯示部分內容等等。Recordset對象也包含Fields集合,FIElds集合中有記錄集中每一個字段(列)的Filed對象。
無論是在ASP頁面中處理數據,還是利用遠程數據服務(RDS)遠程使用數據,Recordset對象是必須處理的對象。
8.2.4 Record對象
ADO 2.5以前的版本在處理結構化數據上是很有效的,比如從數據庫中取出記錄集,但無法處理每一行的列(也就是列數和數據類型)可能不同的數據。對於SQL數據這不是一個問題,但對於文件和郵件系統,Web服務器和別的諸如此類的數據存儲會如何呢?我們把這些數據看作是半結構化的數據,與記錄集相比結構性較差,但與那些常用來代表文本或圖像的二進制數據相比更具有結構性。
通常,半結構化數據的存儲采用樹狀結構來組織,有節點、子節點和文件。例如,設想一個有文件夾、子文件夾和文件的Web站點。圖8-4所示的屏幕圖顯示了一台機器的Web站點,特別是還有一個名為public的虛擬目錄:
圖8-4 顯示了一台機器的Web站點的界面
如果一定要在ADO中進行建模,會覺得這非常適合記錄集,可能是嵌套的記錄集。然而注意高亮度顯示的目錄,該目錄含有不同類型的文件,裡面有幾個目錄、兩個ASP文件、一個文本文件和一個Word文檔。你會很容易地將其映射到一個擁有名稱、類型、上次存取時間等字段的記錄集,遺憾的是並不是這樣簡單。對於訪問權限而言,在文件和目錄之間就有區別。對於目錄,需要的是能訪問目錄下的文件;而對於文件,卻可能是需要訪問其內容。
由於其復雜性,引入了Record對象。在上面的情況下,存在有一些相同屬性的條目的一個集合,但是每個條目也有獨特的屬性,因此需要使用別的方法去處理這些數據。把一個集合映射到一個記錄集,一個單獨的文件映射成一條記錄,相應的文件屬性就映射成FIElds集合。
這意味著有了一個含有六行記錄的記錄集。訪問記錄集中單獨的一行就會得到該文件的屬性(字段),但是提供給我們的僅僅是屬性,為了訪問文件或目錄的內容,需要使用Record對象,該對象包含文件或目錄的獨特屬性。習慣於這個概念有一定的困難,但不必擔心,在第11、12章你會看到更多有關Record對象的例子。
Windows 2000初始版本發布以來,只有用於Internet發布的OLE DB提供者使用Record對象。一旦微軟Exchange 6.0發布,將成為以類似方法利用記錄集和記錄提供對Exchange信息庫訪問的OLE DB提供者。