選擇正确的API從SQL Server擷取XML資料。
by Greg Ewing and Jon Rauschenberger
技術工具箱: C#, SQL Server 2000, ASP.NET, XML, VB6
.NET Framework包含幾個新的資料存取APIs,每種API對通路SQL Server中XML資料的支援程度都不同。在如何完成你的解決方案、需要寫多少代碼方面,選擇不同的API将會有不同的結果。在本專欄中,我将闡述Microsoft的四種XML資料存取APIs:ActiveX Data Objects (ADO) 2.6、ADO.NET、SqlDataReader和 SQLXML。
我們将重點講述實作每種API需要的代碼,并比較每種API提供的性能和可擴充性。通過一步步建構查詢一個Northwind資料庫所需要的代碼,将結果轉化成XML,我們來逐個說明這些API。然後通過對它們進行一些負載測試,我們來看看它們的性能如何。
要确定哪種XML資料存取API能夠最好地滿足你的需求,你需要考慮幾個因素。首先,看一下每種API需要的代碼量。然後,考慮你有多大的靈活性來控制API傳回的XML格式。有時候,你不能控制XML的格式。最後,考慮API是如何執行和擴充的。因為SQL Server沒有将本地資料存為XML,是以将資料從本地的SQL Server二進位格式轉換成XML所需要的費用可能很高,可能會限制你的應用程式的性能和可擴充性<?xml version="1.0" encoding="utf-16"?>
ADO是一個受歡迎的資料存取API。Microsoft最初在ADO 2.1中增加了将結果集轉換成XML的支援功能,這就使你可以将一個結果集存為一個XML檔案。相對于ADO 2.6對XML有限的支援,ADO.NET增加了許多新的XML功能。ADO.NET DataSet對象支援将結果集串行化成格式規範的XML。
讓我們開始做個樣例程式吧,打開VS.NET,建立一個新的C#類庫。将Class1.cs重新命名為DBXml.cs,并取消名字空間。然後,添加引用System.Data.dll,它包含ADO.NET名字空間。接着,打開ADONet類并引入這些名字空間:
|
現在,給DBXml 類添加代碼,連接配接到資料庫并用ADO.NET來執行SELECT語句(見清單1)。ExecuteSelect函數做的第一件事就是通過傳遞連接配接字元串到構造器用SqlConnection類來初試化一個到資料庫的連接配接。然後,建立 SqlDataAdapter,将SELECT語句和連接配接對象傳遞到構造器中。SELECT語句有一個參數用于你選擇的使用者的ID,是以你必須将那個參數添加到SelectCommand Parameters集合中。Add函數可以接受參數的名字、資料類型、大小和列的關連。一旦這個參數是集合的一部分,你需要給它賦以正确的值。
下面的兩步,建立DataSet并用擴充卡填充它,完成了大部分工作。如果連接配接沒有打開,用DataAdapter上的Fill方法來打開連接配接,或者用已打開的連接配接,它通常傳回到最初的狀态。然後,你用GetXML函數将DataSet轉換成XML字元串,傳回給調用者。<?xml version="1.0" encoding="utf-16"?>
運用SqlDataReaderSqlDataReader為資料存取提供了一個連續的、隻讀的指針,使其成為從SQL Server讀取資料的最快的方式。DataReader對XML沒有提供本地的支援,是以你必須自己寫XML轉換代碼或運作一個傳回XML的查詢過程。對于這個例子,你可以用FOR XML RAW子句讓SQL Server傳回XML的資料。
運用SqlDataReader,寫代碼來執行SELECT語句并傳回XML的結果(見清單2)。該方法中的第一行代碼同ExecuteSelect函數一樣。同DataSets一樣,SqlDataReader依賴于一個SqlConnection對象。通過将SQL語句和Connection對象傳遞到構造器來建立Command對象。
在打開資料庫連接配接後,通過給SqlDataReader賦以Command.ExecuteReader方法的傳回值來建立SqlDataReader。然後,用StringBuilder類從SqlDataReader讀取XML。在處理大的字元串方面,StringBuilder類比String類的字元串處理方法更有效。
調用 GetString(0)來得到與目前行的資料相關的字元串。結果集在一個很長的XML字元串中,是以你隻需要反複調用read(),直到DataReader為空。一旦你建立了字元串,隻需要把它傳回給調用者就行了。
運用VS.NET得到XML資料的最後一個方法就是通過運用SQLXML托管類,它們是SQLXML 3.0功能包的一部分(見資源)。SQLXML功能包擴充了SQL Server 2000的XML功能。3.0版本中的托管類是.NET Framework的本地類,它們可以使用新增加的XML功能。
<?xml version="1.0" encoding="utf-16"?>
SQLXML 3.0的安裝将Microsoft.Data.SqlXml集合裝到你的機子上。給項目添加對該集合的一個引用,并用以下代碼引入名字空間:
|
以下代碼連接配接到資料庫,并用SQLXML類來執行SELECT語句:
|
該代碼所做的第一件事就是通過将連接配接字元串傳遞到構造器來建立必要的SqlXmlCommand對象。由FOR XML建立的XML通常是一個XML片段,并不是格式規範的檔案。為了使XML格式規範,你必須用RootTag屬性在Command對象上設定一個根标簽,在本例中設定成“employees”。<?xml version="1.0" encoding="utf-16"?>
SQLXML功能包的以前的版本在将XML傳回給用戶端前在資料庫伺服器上構造XML。這會造成可擴充性方面的問題,因為建立的XML沒有分布給用戶端,是以産生的XML流比預設情況下SQL Server傳回的本地二進位資料流要大很多。3.0版本允許SQLXML将資料流作為二進位資料傳回給用戶端,然後在用戶端上将資料轉換成XML。
将資料轉換成XML将ClientSideXml屬性設定成True來實作這一步。你仍然用帶有FOR XML子句的SELECT語句,但是當你将ClientSideXml設定為True時,在将語句傳送到SQL Server前,托管類将FOR XML子句從SQL語句中去掉了。資料庫不再看到FOR XML子句,可以更有效地将資料流傳回給用戶端。然後,SQL托管類在用戶端将資料流轉換成XML。
通過調用ExecuteXmlReader方法來執行SELECT語句,該方法傳回一個XmlReader對象。然後,你将XmlReader對象載入一個XmlDocument,并将産生的OuterXml傳回給調用者。
最後一個資料存取API是運用ADO 2.6和Visual Basic 6.0。通過打開一個新的VB6 ActiveX DLL項目來建立這個項目。重新命名Class1為ADO26,命名項目為DBXMLVS6。然後,給項目添加ActiveX Data Objects 2.6引用。一旦完成這一步,就給你的類添加ExecuteSelect方法(見清單3)。
同所有其它例子一樣,你先要建立并打開你的資料庫連接配接。然後,建立新的Command對象,并給Connection對象設定其ActiveConnection屬性。SELECT語句同ADO.NET例子中用的SELECT語句一樣。
圖1. 看看哪種API最快 |
将Execute方法的傳回值設定給RecordSet對象。你需要建立一個ADO Stream對象将結果集轉換成XML。将Stream的Type屬性設定成adTypeText,并打開它。打開後,在你的結果集上調用Save方法,指明你想把結果集儲存為XML。一旦XML在資料流中,用ReadText方法将它傳回給調用者。
通過建立簡單的ASP和ASP.NET頁面,調用元件并将XML傳回給浏覽器,我們就可以測試每種API實作的性能和可擴充性(在圖1中可以看到結果,關于更詳細的結果,請參考工具條“測試記錄”。關于這些ASP和ASP.NET頁面,請在此下載下傳代碼。)
随着Microsoft不斷增加新的功能并改進性能,XML資料存取APIs也在不斷發展。因為未來的SQL Server版本将增加對XML的本地支援,而且APIs通過利用這些功能得以不斷增強,是以API不斷發展的這個趨勢也将持續下去。然而,如今現有的APIs已經提供了強大的功能和性能組合,可以使你建構高性能的XML應用程式。
關于作者:
Greg Ewing是Clarity Consulting Inc.的顧問。除了為VSM、MSDN和内部刊物撰寫文章外,Greg還負責幾種技術的内部教育訓練,包括C#、進階VB.NET、C++和COM。他的聯系方式是[email protected]。
Jon Rauschenberger是Clarity Consulting Inc.的合作夥伴和技術主管,這是一家位于芝加哥的資訊技術咨詢公司和Microsoft Gold Certified Partner。除了建構可擴充的基于 Web的解決方案外,Jon也在諸如Microsoft Tech-Ed、VBITS、COMDEX和DevDays這樣的大會上做演講。Jon也是芝加哥MSDN地區主管。聯系方式[email protected]。
轉載于:https://www.cnblogs.com/ghx88/archive/2006/06/14/425770.html