在Microsoft Office System中使用ADO.NET資料集(三)
來源:互聯網
上載者:User
ado|資料 到這一步,你的DataSet應該完全被來自資料庫中的資料填充了,因此你可以關閉資料庫連接對象。儘可能早的關閉串連永遠是一個好的編程習慣,這樣你可以將它釋放給其他應用程式。另一方面,如果當前程式將要立即使用這個串連——也許是為了建立另一個DataSet,你可以保持它為開啟狀態以避免重建該串連帶來的額外開銷。
注意:如果你在該應用程式中對每個串連重用完全相同的連接字串——包括嵌套空間,預設情況下,ADO.NET將共用同一個串連。因此在大多數情況下,關閉和重新開啟一個串連只會導致非常小的開銷(可以忽略不計)。
我們可以說,現在你的DataSet已經填充完畢,並且準備好以供使用,同時從資料庫斷開了串連。在許多應用程式程式中,這些就是你所需要的,但是你可能希望建立多種關係,用以建立資料的分級特性。建立這些關係需要使用DataRelation類。
重點 即使你在你的資料庫中定義了相關的完整性關係,你也沒有方法在一個DataSet中自動重建這些關係——換句話說,你必須手工建立這些關係。
建立一個資料關係需要引用DataSet中現存表兩個以上的列。下面的代碼中使用parent和child DataColumn對象來在兩個表中的主鍵與外鍵之間添加關係。一旦你執行個體化這些對象(parent和child對象),你就可以執行個體化DataRelation對象,並傳遞給其一個名字,用以標識關係屬於parent 和child 對象。
代碼還設定關係的Nested(嵌套)屬性為 True.當你讀取該DataSet的XML表示時,child元素並不會自動嵌套到它的parent對象中。相反,所有的parent元素先被列出來,所有的child元素緊隨其後,並按層次進行分組。雖然種非常有用的結構是罕見的,但是Nested屬性嵌套了資料。
最後一步,添加新的DataRelation對象到該DataSet對象的Relations集合中。注意到,代碼中是使用表的名字作為參考資料表識的。你可以將它們替換為你自己的表的名字。
'Add the relationships to the DataSet
'Customers -> Orders
Dim parent As DataColumn = _
ds.Tables("Customers").Columns("CustomerID")
Dim child As DataColumn = ds.Tables("Orders").Columns("CustomerID")
Dim sqlRel As New DataRelation("Customer Orders", parent, child)
sqlRel.Nested = True
ds.Relations.Add(sqlRel)
該過程的最後一步將DataSet對象的XML架構和資料儲存到硬碟上。使用DataSet時這一步不是必須的,但是在“將DataSet作為XML匯入到Excel 2003 Worksheet”節,你將看到如何使用它們。
大多數.NET Frameword對象支援序列化成一維或多維,但是,DataSet對象使序列化變得更為簡單——使用WriteXml和WriteXmlSchema方法就能做到。當你調用這兩個方法使,需要傳遞相應磁碟檔案的名字給每個方法,資料就儲存到相應的檔案中。你可以提供完整路徑,但是這段代碼將檔案儲存到應用程式的bin檔案夾。在這裡有用到表名稱作為引用標誌。
‘可選步驟:將XML資料和架構儲存為磁碟檔案
If bSaveSchema Then
'Places the file in this app's bin directory
ds.WriteXmlSchema("Customers.xsd")
ds.WriteXml("Customers.xml")
End If
該過程將完整的DataSet對象返回給調用它的過程。
Return ds
End Function
為單一實體建立DataSet
當你在一個用戶端應用程式中建立一個DataSet時,ADO.NET將來自資料庫的所有資料通過網路傳遞到用戶端,並盡最大可能將必需資料完全填充到這個DataSet中。
如果你的表有數百萬條記錄,將會發生什嗎?你希望通過網路傳遞儘可能少的資料填充到DataSet中,例如,你很可能僅僅希望得到單一某個客戶的資訊。在Northwind資料庫中,資料訪問層的類方法GetCustomerDataSet就是實現這個功能的,它使用使用者從表單上的下拉式清單方塊中所選擇的CustomerID作為參數來選定某個特定客戶。
你需要的代碼與GetDataSet中的代碼極為類似,但是有一些重要的不同點。首先,你現在需要過濾資料。也就是說,你必須過濾表中的資料,以便只返回必需的記錄,並且對任何相關表都要執行這些操作,但是若有多個表一般就會返回多個記錄,例如:篩選出客戶已經下的訂單的某個(一個客戶可能下0個或多個訂單)。
你可以對DataSet中所容納的資料執行篩選和排序,但是這意味著整個資料集都將穿越網路。一個好的方式是在資料庫端執行篩選和排序,並且只返回必需的記錄。
你可以通過SqlParameter對象執行篩選。這些參數應用於代碼中的每個動態SQL語句,注意,執行這樣的方法與調用相應的預存程序是等效的。
下面的代碼填充DataSet中的Customers表。注意到現在的SQL語句有一個WHERE子句,沒有ORDER BY子句——對單一某個記錄是不必排序的。該SqlCommand對象和前面一樣的方式執行個體化,但是現在它需要設定@CustID參數。SqlParameter對象用參數名——@CustID,和參數類型——nchar(5)執行個體化。然後它設定參數的Value屬性為傳遞到該過程的值。最後一步是添加這個新參數叨命令對象的Parameters集合中,然後調用資料配接器的Fill(同前面的步驟)。SQL語句需要多少參數,你就可以添加多少參數對象。
Dim sql As String = "SELECT CustomerID, CompanyName, ContactName, " _
ContactTitle, Address, City, Region, PostalCode, Country, " _
& "Phone, Fax FROM Customers WHERE CustomerID = @CustID"
Dim sqlCmd As New SqlCommand(sql, sqlCnn)
Dim sqlParam As New SqlParameter("@CustID", SqlDbType.NChar, 5)
sqlParam.Value = sCustID
sqlCmd.Parameters.Add(sqlParam)
Dim sqlDA As New SqlDataAdapter(sqlCmd)
sqlDA.Fill(ds, "Customers")
另一些表以幾乎完全相同方法填充,除了某些被過濾的表需要合并到Orders表中,這樣CustomerID才可以訪問。
每個子表需要重用SqlParameter對象,因為它們都需要過濾CustomerID,而不僅僅只Products表用到。你希望返回資料庫中的所有產品,而不管該產品是否被訂購。因此,該代碼的這個部分調用了Parameters集合的Clear方法。