上圖顯示了ADO.NET對象模型中的類。左邊的是連接對象,這些對象直接與數(shù)據(jù)庫通信,以管理連接和事務(wù),以及從數(shù)據(jù)庫檢索數(shù)據(jù)和向數(shù)據(jù)庫提交所作的更改。右邊的是非連接對象,允許用戶脫機處理數(shù)據(jù)。下面我們逐個了解這些類的作用 一、連接對象 1、.NET數(shù)據(jù)提供程序 .NET數(shù)據(jù)提供程序是一個類的集合,專門設(shè)計用來同特定類型的數(shù)據(jù)存儲區(qū)進行通信。在.NET Framework中,包含了四種此類提供程序:SQL Client.NET數(shù)據(jù)提供程序、Oracle Client.NET數(shù)據(jù)提供程序、ODBC.NET數(shù)據(jù)提供程序和OLE DB.NET數(shù)據(jù)提供程序。 每種.NET數(shù)據(jù)提供程序都實現(xiàn)相同的基類:ProviderFactory,Connection,ConnectionStringBuilder,Command,DataReader,Parameter和Transaction,只是其實際名稱取決于該數(shù)據(jù)提供程序。例如SQL Client.NET數(shù)據(jù)提供程序具有SqlConnection類,而ODBC.NET數(shù)據(jù)提供程序包含OdbcConnection類。無論使用哪種.NET數(shù)據(jù)提供程序,此數(shù)據(jù)提供程序的Connection類都通過相同的基類接口實現(xiàn)相同的基本特性。要對數(shù)據(jù)存儲區(qū)打開一個連接,可創(chuàng)建此提供程序連接類的一個實例,設(shè)置此對象的ConnectionString屬性,然后調(diào)用其Open方法即可。
每個.NET數(shù)據(jù)提供程序都有自己的命名空間。.NET Framework中所包含的4個提供程序是System.Data命名空間的一個子集,非連接對象就位于System.Data命名空間之中。SQL Client數(shù)據(jù)提供程序位于System.Data.SqlClient命名空間中,ODBC.NET 數(shù)據(jù)提供程序位于System.Data.Odbc命名空間中;OLE DB.NET數(shù)據(jù)提供程序則位于System.Data.OleDb命名空間中;Oracle Client.NET數(shù)據(jù)提供程序位于System.Data.OracleClient命名空間中。
為什么微軟要用分離的類和庫? 過去微軟使用的ADO技術(shù),并沒有針對不同的數(shù)據(jù)提供程序,提供不同的類,為什么在ADO.NET中要這么做,主要出于性能、擴展性的考慮:
在使用ADO技術(shù)時,實際上是將ADO接口用作于數(shù)據(jù)存儲區(qū)進行通信時的“中介”。開發(fā)人員告訴ADO,自己希望使用哪個提供程序,而ADO將開發(fā)人員的調(diào)用傳遞給適當?shù)臄?shù)據(jù)提供程序,而后該數(shù)據(jù)提供程序就會執(zhí)行所請求的操作,并通過ADO庫返回結(jié)果。 而在ADO.NET中,數(shù)據(jù)提供程序不涉及中間層。開發(fā)人員直接與對應(yīng)的數(shù)據(jù)提供程序通信,該數(shù)據(jù)提供程序使用數(shù)據(jù)存儲區(qū)的低級編程接口與數(shù)據(jù)存儲區(qū)通信。使用ADO.NET的SQL Client.NET數(shù)據(jù)提供程序域SQL Server通信要快于ADO和SQL Server OLE DB提供程序,原因就在于少涉及一層。
在SQL Server 2000引入XML特性時,ADO開發(fā)小組就面臨著一項很有意義的挑戰(zhàn)。為了給ADO添加能使開發(fā)人員從SQL Server 2000中檢索XML數(shù)據(jù)的特性,ADO開發(fā)小組就必須為OLE DB API以及SQL Server OLE DB提供程序添加新的接口。 .NET數(shù)據(jù)提供程序更容易擴展。它們只需要支持相同的基礎(chǔ)接口,并可以在適當?shù)臅r候提供額外的提供程序?qū)iT功能。OLE DB.NET數(shù)據(jù)提供程序的Command對象所公開的全部方法和屬性,SQL Clien.NET數(shù)據(jù)提供程序的Command對象(SqlCommand)也均予以公開,此外還添加了一個新的方法,以獲得以XML方式返回的程序結(jié)果。 SQL Server 2005包含了一組新的特性,例如能夠使應(yīng)用程序利用通知服務(wù),以便在服務(wù)器上查詢結(jié)果發(fā)生變化時收到通知。微軟并沒有改變ADO.NET公開類的內(nèi)部工作,而只是想SQL Client.NET數(shù)據(jù)提供程序添加了兩個新類,以充分利用這些新的SQL Server特性。
2、連接對象
ProviderFactory類是ADO.NET2.0中新增的類,相當于一個對象工廠,使開發(fā)人員能夠為.NET數(shù)據(jù)提供程序創(chuàng)建其他類的實例。每個ProviderFactory都提供一種Create方法,此方法創(chuàng)建Connections,ConnectionStringBuilders,Commands,Parameters,DataAdapters和CommandBuilders。
表示與數(shù)據(jù)庫的連接。可通過Connection的不同屬性指定數(shù)據(jù)源的類型、位置。它起到渠道的作用,其他對象如DataAdapter和Command通過它與數(shù)據(jù)庫進行通信,以提交查詢和獲取查詢結(jié)果,下面這幅圖很形象的說明了Conneciton所承擔的橋梁作用。 (備注:這幅圖使用了冠華仔博文http://www.cnblogs.com/gishuazi/archive/2009/03/05/1403823.html中的圖:_))
ConnectionStringBuilder類也是ADO.NET2.0中新增的,它簡化了為.NET數(shù)據(jù)提供程序建立連接字符串的過程,每個ConnectionStringBuilder類都公開一些屬性,這些屬性對應(yīng)于可在.NET數(shù)據(jù)提供程序的連接字符串中使用的選項。例如SqlConnectionStringBuilder類有DataSource屬性,用于指定數(shù)據(jù)源的位置,InitialCatalog屬性用于指定連接哪個數(shù)據(jù)庫,IntegratedSecurity屬性用于指定使用何種方式連接。
Command對象可表示對數(shù)據(jù)庫的查詢,對存儲過程的調(diào)用,或者返回特定表內(nèi)容的直接請求。數(shù)據(jù)庫支持多種不同類型的查詢。有些查詢通過引用一個表或多個表、視圖或者是通過調(diào)用一個存儲過程來獲取數(shù)據(jù)行,有些查詢則會對數(shù)據(jù)行進行修改,還有一些查詢通過創(chuàng)建或修改諸如表、視圖或存儲過程對象來對數(shù)據(jù)庫的結(jié)構(gòu)進行有關(guān)操作。Command對象都能夠支持。
DataReader用于以最快的速度檢索并檢查查詢所返回的行。可使用DataReader對象來檢查查詢結(jié)果,一次檢查一行。當移向下一行時,前一行的內(nèi)容就會被丟棄。DataReader不支持更新操作。由DataReader返回的數(shù)據(jù)時只讀的。由于DataReader對象支持最小特性集,所以它的速度非產(chǎn)快。
有時可能希望將對數(shù)據(jù)庫所作的所有更改組織起來,將它們看做一個獨立的工作單元。在數(shù)據(jù)庫編程中,這樣的工作單元就成為事務(wù)(Transacton)。假設(shè)某數(shù)據(jù)庫包含銀行的客戶信息,還有支票賬戶表和儲蓄賬戶表,一位用戶想要將錢從儲蓄賬戶轉(zhuǎn)到支票賬戶中去。在所編寫的代碼中,希望確保儲蓄賬戶的提款操作和支票賬戶的存款操作是一個獨立的單元,要么同時成功完成,要么兩項操作都不發(fā)生,這就可以通過事務(wù)來實現(xiàn)。 Connection對象有一個BeginTransaction方法,可以用來創(chuàng)建Transactio對象。
在查詢語句中,我們希望通過Where子句來限定條件,這些條件,如果希望在運行時動態(tài)指定,那么我們可以通過Parameter對象來實現(xiàn)。我們可以通過為查詢中的所有參數(shù)創(chuàng)建Parameter對象,并將它們添加到Command對象的Parameter集合中。
就像上面那幅圖所示的,DataAdapter負責搬運數(shù)據(jù)到DataSet中,DataAdapter對象的Fill方法提供了一種高效機制,用于將查詢結(jié)果引入DataSet或DataTable中,以便能夠脫機處理數(shù)據(jù)。還可以利用DataAdapter對象向數(shù)據(jù)庫提交存儲在DataSet對象中的掛起更改。 DataAdapter公開了大量屬性,這些屬性實際上是Command對象。例如SelectCommand屬性包含一個Command對象,該對象表示將用來填充DataSet對象的查詢。此外,DataAdapter還有UpdateCommand、InsertCommand和DeleteCommand等屬性,這么做是為了允許開發(fā)人員定義自己的更新邏輯。 二、非連接對象 1、DataTable類 ADO.NET的DataTable類運行我們通過行和列的集合來查看數(shù)據(jù)??梢酝ㄟ^DataAdapter對象的Fill方法將查詢結(jié)果存儲在DataTable中: Dim conn As SqlConnection '完成連接數(shù)據(jù)庫和填充數(shù)據(jù) conn = New SqlConnection("Data Source=(local);Initial Catalog=JWInfo;Integrated Security=True") dataSet = New DataSet() 在從數(shù)據(jù)庫中讀出數(shù)據(jù)并將其存儲在DataTable對象之后,該數(shù)據(jù)即從服務(wù)器斷開連接。然后就可以脫機查看DataTable對象的內(nèi)容,而不會在ADO.NET和數(shù)據(jù)庫之間產(chǎn)生任何網(wǎng)絡(luò)通信流量。DataTable類包含了其他非連接對象的集合,例如可以通過DataTable的Rows屬性訪問其內(nèi)容,這一操作將返回DataRow對象的一個集合。如果希望查看DataTable表的結(jié)構(gòu),則可以使用其Columns屬性來獲取DataColumn的對象集合。DataTable還允許為該類中存儲的數(shù)據(jù)定義一些約束,如主鍵。可以通過DataTable對象的Constrains屬性訪問這些約束。 2、DataColumn類 每個DataTable都有一個DataColum的集合,該集合時DataColum對象的容器,從其名稱可以看出,一個DataColumn對象對應(yīng)于表中的一列,然而,DataColumn對象并非實際包含存儲在DataTable中的數(shù)據(jù),而是存儲了有關(guān)該列的結(jié)構(gòu)信息,例如數(shù)據(jù)類型,是否是只讀的,是否允許存儲Null值,是否是唯一的等等。 DataColumn類還包含一個Expression屬性,用來指定如何計算列中的數(shù)據(jù)。通常我們會通過表達式來計算查詢中一個列的值,例如: SELECT OrderID, ProductID, Quantity, UnitPrice, Quantity*UnitPrice AS ItemTotal From [Order Details] 這樣做的缺點是:數(shù)據(jù)庫引擎只會在查詢時執(zhí)行計算。如果修改了DataTable對象中的UnitPrice或者Quantity列的內(nèi)容,ItemTotal列不會發(fā)生任何變化。 ADO.NET的DataColumn類定義了一個Expression屬性來完美地解決這個問題。當基于一個表達式來檢查DataColumn對象的值時,ADO.NET會計算該表達式,并返回一個最新的值。這樣,如果更新了表達式中任一列的值,存儲在計算列中的值都是準確的。下面是具體的使用方法: DataColumn col=new DataColumn(); col.ColumnName="ItemTotal"; col.DataType=typeof(Decimal); col.Expression="UnitPrice * Quantity"; 3、Constriant類 DataTable類還提供了一種方式,用于對DataTable對象中本地存儲的數(shù)據(jù)設(shè)置約束。例如,可以建立一個Constraint對象,確保某一列或多列中的值在DataTable中式唯一的。Constraint對象存在于DataTable的Constraints集合中。 4、DataRow類 要想訪問存儲在DataTable對象中的實際值,可以使用此對象的Rows集合,該集合中包含一組DataRow對象。要想查看存儲在特定行、特定列中的數(shù)據(jù),可以使用對應(yīng)DataRow對象的Item屬性來讀取該行中任意列的值。DataRow的Item屬性有多個重載版本,可以通過指定列名稱,索引值,甚至DataColumn對象來明確要查看哪一列。由于Item是DataRow的默認屬性,因此可以隱式地使用它: DataRow row; row=tbl.Rows[0]; Console.WriteLine(row[0]); Console.WriteLine(row["CustomerID"]); Console.WriteLine(row[MyTable.Columns["CustomerID"]]); 可以通過調(diào)用DataRow對象的BeginEdit方法,通過Item屬性修改此行中的一些列的值,然后通過EndEdit方法來講更改保存到改行中。通過調(diào)用DataRow的CancelEdit方法,可以取消在當前編輯會話中所作的修改。 需要注意的是,在改變了一行的內(nèi)容時,DataRow對象會緩存這些更改,從而可以在以后想數(shù)據(jù)庫提交他們。 5、DataSet類 從其名稱可以看出,DataSet對象包含一個數(shù)據(jù)集??梢詫ataSet對象視為許多DataTable對象(它們存儲在DataSet對象的DataTables集合中)的容器,也就是說相當于一個內(nèi)存的數(shù)據(jù)庫。ADO.NET的目的是幫助開發(fā)人員建立大型的多層數(shù)據(jù)庫應(yīng)用程序。有時,開發(fā)人員可能希望訪問一個運行在中間層服務(wù)器上的組件,以獲取許多表的內(nèi)容。這時不必重復(fù)調(diào)用該服務(wù)器以便每次從一個表中獲取數(shù)據(jù),而是可以將所有的數(shù)據(jù)都裝入一個DataSet對象中,并在一次單獨調(diào)用中將其返回。但DataSet對象的功能絕不僅僅作為多個DataTable對象的容器。 存儲在DataSet對象中的數(shù)據(jù)未與數(shù)據(jù)庫連接。對數(shù)據(jù)所作的任何修改都將只是緩存在每個DataRow中。要將這些更改傳遞給數(shù)據(jù)庫時,將整個DataSet對象回傳給中間層服務(wù)器可能并非一種有效方法??梢允褂肎etChanges方法僅從DataSet中選出被修改的行。通過這樣的方式,可以在不同進程或服務(wù)器之間傳遞較少的數(shù)據(jù)。 DataSet還公開了一個Merge方法,該方法可以作為GetChanges方法的一個補充。用于向數(shù)據(jù)庫提交更改的中間層服務(wù)器(它使用的是由Merge方法返回的較小的DataSet)將會返回一個包含著新獲得數(shù)據(jù)的DataSet。可以使用DataSet類的Merge方法來將兩個DataSet對象的內(nèi)容合并入一個DataSet中。 我們還可以在不建立與數(shù)據(jù)庫連接的情況下,就是用信息填充DataSet對象的Tables表集合。在以前的數(shù)據(jù)庫編程模型中,在本地添加新行之前,通常需要查詢數(shù)據(jù)庫,然后將它們提交給數(shù)據(jù)庫。而使用ADO.NET,在準備好提交數(shù)據(jù)行之后,才需要與數(shù)據(jù)庫通信。 6、DataRelation類 數(shù)據(jù)庫中的表,通常以某種方式相關(guān)聯(lián)。例如,在Northwind數(shù)據(jù)庫中,Orders表中的每個項都與Customers表的一個表項相關(guān)聯(lián),因此可以確定哪位客戶下了哪些訂單。ADO.NET的DataRelation對象借助于DataRelation類來處理來自相關(guān)DataTable對象的數(shù)據(jù)。 DataTable類公開了一個Relations屬性,該屬性是DataRelation對象的一個集合??梢允褂肈ataRelation對象來表示DataSet中不同DataTable對象之間的關(guān)系。 DataSet ds; DataTable tblCustomers,tblOrders; DataRelation rel; //……創(chuàng)建并初始化DataSet rel=ds.Relations.Add("Customers_Orders",tblCustomers.Columns["CustomerID"],tblOrders.Columns["CustomerID"]); foreach(DataRow rowCustomer in tblCustomers.Rows) { Console.WriteLine(rowCustomer["CompanyName"]); foreach(DataRow rowOrder in rowCustomer.GetChildRows(rel)) Console.WriteLine("{0}",rowOrder["OrderID"]); Console.WriteLine(); } 7、DataView類 在將一查詢結(jié)果置于DataTable對象中以后,就可以使用DataView對象以不同的方式來查看數(shù)據(jù)。如果希望根據(jù)某一列對DataTable對象的內(nèi)容進行排序,只需要將DataView的Sort屬性設(shè)置為該列的名稱即可。還可以設(shè)置DataView的Filter屬性,使得只有符合特定標準的行可見。 可以使用多個DataView對象同時查看同一個DataTable。例如在一個窗體中可以擁有兩個表格,其中一個用于按照字母順序顯示所有客戶,另一個則按照國家進行排序。為了顯示所有視圖,需要將每個表格綁定到不同的DataView對象。 |
|