ADO与ADO.NET
今天老板又提到了客戶端游標(biāo)與服務(wù)端游標(biāo),并給我們講了性能差別。但是....我用了好久的.NET,都忘了很久很久以前曾經(jīng)的ADO,原來(lái)老板是在講ADO的游標(biāo)類型。嗚~回來(lái)翻了下網(wǎng),找了以下的內(nèi)容重新學(xué)習(xí)一下:
您可以使用無(wú)數(shù)種方法在 VB6 和 VB.NET 中處理數(shù)據(jù)。這兩個(gè)平臺(tái)都支持諸如數(shù)組和集合之類的結(jié)構(gòu),開發(fā)人員通常將自定義類包裝到這些結(jié)構(gòu)中,就如您在 Carl Ganz 2004 年 3 月的專欄中看到的那樣。數(shù)據(jù)獨(dú)立(這可能是創(chuàng)建自定義數(shù)據(jù)抽象層的最大優(yōu)勢(shì))允許用戶在獨(dú)立于數(shù)據(jù)庫(kù)的情況下操作數(shù)據(jù)。這不僅降低了服務(wù)器的負(fù)擔(dān),還消除了維護(hù)到該數(shù)據(jù)庫(kù)的開放連接的需要,或是對(duì)忘記更新 RDBMS 的擔(dān)心。本月,Carl 將分析如何同時(shí)使用 ADO 和 ADO.NET 來(lái)創(chuàng)建此類數(shù)據(jù)對(duì)象。
在 VB6 中,OLE DB 游標(biāo)服務(wù)允許您創(chuàng)建通常作為虛構(gòu)的Recordset 的內(nèi)容。這些只是 ADO Recordset 對(duì)象的內(nèi)存中實(shí)例,Field 對(duì)象將添加到這些實(shí)例中以形成一個(gè)數(shù)據(jù)結(jié)構(gòu)。您需要顯式創(chuàng)建這些 Recordset 客戶端,如清單 1 中所示;默認(rèn)情況下,它們是在服務(wù)器端創(chuàng)建的,您在服務(wù)器上不能有離線 Recordset。
Set oRS = New ADODB.Recordset oRS.CursorLocation = adUseClient oRS.CursorType = adStatic oRS.LockType = adLockBatchOptimistic 'Add a few fields With oRS.Fields.Append "LastName", adVarChar, 40, adFldIsNullable.Append "FirstName", adVarChar, 40, adFldIsNullable.Append "HireDate", adDate End With oRS.Open一旦創(chuàng)建 Recordset,您就可以用數(shù)據(jù)填充它了。請(qǐng)注意,Field 集合的 Append 方法只能用于關(guān)閉的 Recordset;如果您在打開 Recordset 的 Fields 集合上或是已設(shè)置 ActiveConnection 屬性的 Recordset 上調(diào)用 Append,就會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。清單 2 闡釋了如何將數(shù)據(jù)添加到 Recordset 對(duì)象。
清單 2 中的最后兩行代碼闡釋了如何創(chuàng)建索引,以使排序更加高效。(通常,您應(yīng)通過(guò)一個(gè)提供初始排序的 SQL 命令來(lái)加載此類數(shù)據(jù),但是如果數(shù)據(jù)在網(wǎng)格中,您可能希望允許用戶通過(guò)(比如說(shuō))單擊列標(biāo)題來(lái)排序它。)
清單 2. 用數(shù)據(jù)填充 Recordset 對(duì)象。
'Populate with some data oRS.AddNew Array("LastName", "FirstName", "HireDate")_, Array("Washington", "George", "3/12/2003") oRS.AddNew Array("LastName", "FirstName", "HireDate")_, Array("Adams", "John", "8/5/2003") oRS.AddNew Array("LastName", "FirstName", "HireDate")_, Array("Jefferson", "Thomas", "4/27/2003") oRS.Update 'Create an in-memory index oRS.Fields("LastName").Properties("Optimize").Value _= True'Sort on first name oRS.Sort = "FirstName"創(chuàng)建 Recordset 的另一種方法涉及到離線 Recordset。這只是一個(gè) Recordset 對(duì)象,它隨后將連接到由于將 ActiveConnection 屬性設(shè)置為 Nothing 而離線的服務(wù)器(請(qǐng)參見清單 3)。
清單 3. 創(chuàng)建離線 Recordset。
Dim objConnection As ADODB.Connection Dim szSQL As String Set objConnection = New ADODB.Connection 'Open a connection objConnection.ConnectionString = "whatever" objConnection.Open 'Instantiate a Recordset object... Set oRS = New ADODB.Recordset oRS.CursorLocation = adUseClient oRS.CursorType = adOpenStatic oRS.LockType = adLockBatchOptimistic '...and set the ActiveConnection property Set oRS.ActiveConnection = objConnection szSQL = "SELECT LastName, FirstName " & _"FROM Employees " & "ORDER BY LastName, FirstName" 'Open the Recordset and return the employee data oRS.Open szSQL Set oRS.ActiveConnection = Nothing objConnection.Close Set DataGrid1.DataSource = oRS使用 ADO.NET
ADO.NET 為離線數(shù)據(jù)管理提供了更強(qiáng)大的功能。DataTable 和 DataSet 對(duì)象本身就定義為離線,因此您不必執(zhí)行任何操作來(lái)使它們離線。從概念上來(lái)說(shuō),ADO.NET DataTable 對(duì)象和 ADO Recordset 對(duì)象的編程創(chuàng)建過(guò)程非常類似,如清單 4 中所示。在本示例中,我們要?jiǎng)?chuàng)建一個(gè) DataTable 對(duì)象,并向其添加列和行對(duì)象。正如您將看到的那樣,ADO.NET 的方法使用了一個(gè)比基于 COM 的 ADO 所使用的更加層次化的對(duì)象模型。
清單 4. 創(chuàng)建 ADO.NET DataTable 對(duì)象。
Dim oDataRow As DataRow Dim oDataColumn As DataColumn Dim aPrimaryKey(0) As DataColumn oDS = New DataSet 'Create a new DataTable oect oEmployeeDT = New DataTable 'Add an event handler for column data changes AddHandler oEmployeeDT.ColumnChanged, _New DataColumnChangeEventHandler(AddressOf _ColumnChanged) 'Create primary key (PK) col and add it to the columns 'collection. Set init value to 1, increment as needed. oDataColumn = New DataColumn oDataColumn.ColumnName = "ID" oDataColumn.DataType = _System.Type.GetType("System.Int32") oDataColumn.AutoIncrement = True oDataColumn.AutoIncrementSeed = 1 oEmployeeDT.Columns.Add (oDataColumn) 'PK property receives array of DataColumn objects in 'case you have multi-col index. I prefer an ID column. aPrimaryKey(0) = oDataColumn oEmployeeDT.PrimaryKey = aPrimaryKey 'Create the individual data columns a€| oDataColumn = New DataColumn oDataColumn.ColumnName = "Salary" oDataColumn.DataType = _System.Type.GetType("System.Decimal") oEmployeeDT.Columns.Add (oDataColumn) 'Here we use DataColumn's Expression property to show 'what a 28% tax on the salary will amount to. oDataColumn = New DataColumn oDataColumn.ColumnName = "IncomeTax" oDataColumn.DataType = _System.Type.GetType("System.Decimal") oDataColumn.Expression = "Salary * .28" oEmployeeDT.Columns.Add (oDataColumn) oDataColumn = New DataColumn oDataColumn.ColumnName = "HireDate" oDataColumn.DataType = _System.Type.GetType("System.DateTime") oEmployeeDT.Columns.Add (oDataColumn) 'This col receives the value calc'd by event handler oDataColumn = New DataColumn oDataColumn.ColumnName = "DaysSinceHire" oDataColumn.DataType = _System.Type.GetType("System.Int16") oEmployeeDT.Columns.Add (oDataColumn) 'Once the columns are added, add sample data oDataRow = oEmployeeDT.NewRow() oDataRow("LastName") = "Washington" oDataRow("FirstName") = "George" oDataRow("Salary") = 45000 oDataRow("IncomeTax") = True oDataRow("HireDate") = "4/12/1981" oEmployeeDT.Rows.Add (oDataRow) a€| 'Commit new data to the DataTable object and set 'RowState values of each row to Unchanged oEmployeeDT.AcceptChanges() 'Let's show the user DataGrid1.DataSource = oEmployeeDT在實(shí)例化 DataTable 對(duì)象之后,您就可以使用這個(gè)事件模型將事件處理程序“DataColumnChangeEventHandler”設(shè)置為自定義例程。通過(guò)傳遞 ColumnChanged 例程的地址,只要一個(gè)列中的數(shù)據(jù)更改,您就可以執(zhí)行這個(gè)處理程序。在本例中,我們要使用它來(lái)確定職員被雇傭以來(lái)的天數(shù)(請(qǐng)參見清單 5)。
清單 5. ColumnChanged 事件處理程序。
Sub ColumnChanged(ByVal sender As Object, _ByVal e As DataColumnChangeEventArgs)If e.Column.ColumnName = "HireDate" Thene.Row("DaysSinceHire") = _DateDiff(DateInterval.Day, _e.Row("HireDate"), Date.Today)End If End Sub由于用戶在網(wǎng)格中編輯數(shù)據(jù)、添加和刪除行,因此每個(gè)行對(duì)象的 RowState 屬性會(huì)更改,以指示所作修改的類型。當(dāng)用戶將離線數(shù)據(jù)提交到 RDBMS 時(shí),需要計(jì)算每一行來(lái)確定用戶執(zhí)行了何種類型的更改。要完成這一操作,您可以通過(guò) GetChanges 方法檢索包含所有新近添加、修改和刪除的行的 DataTable 對(duì)象。然后,循環(huán)訪問(wèn)這個(gè)新 DataTable 中的每個(gè)行對(duì)象并計(jì)算 RowState 屬性,如清單 6 中所示。
清單 6. 標(biāo)識(shí)更改的行并保存更改。
Dim oDataRow As DataRow Dim oChangeDT As DataTable 'Get DataTable with only changed rows oChangeDT = oEmployeeDT.GetChanges() 'Save button s/b disabled until a change is made If oChangeDT Is Nothing ThenExit Sub End If 'Loop thru changed rows, make db updates For Each oDataRow In oChangeDT.RowsSelect Case oDataRow.RowStateCase DataRowState.Added'Insert code hereCase DataRowState.Modified'Update code hereCase DataRowState.Deleted'Delete code hereEnd Select Next oChangeDT.Dispose() oChangeDT = Nothing oDataRow = Nothing 'Issue AcceptChanges method to reset RowState values oEmployeeDT.AcceptChanges()假定我們需要(比如說(shuō))以一對(duì)多 (1:M) 的關(guān)系使用多個(gè)表。因?yàn)閿?shù)據(jù)是相關(guān)的,所以我們可以在一個(gè)單獨(dú)的 DataTable 中管理該信息,并在 DataSet 對(duì)象的保護(hù)下維護(hù)兩個(gè) DataTable 之間的關(guān)系。在以下示例中,我們將為每個(gè)職員指定多種薪水,并在相關(guān)的網(wǎng)格控件中查看它們。通過(guò)使用 DataRelation 對(duì)象,我們可以在兩個(gè)數(shù)據(jù)集之間創(chuàng)建一個(gè)內(nèi)存中關(guān)系,并將 Employee 表的 ID 列用作主鍵 (PK),而將 Paycheck 表的 EmployeeID 列用作外鍵 (FK)。引用完整性 (RI) 原則告訴我們,當(dāng)一個(gè)職員記錄被刪除時(shí),所有關(guān)聯(lián)的薪水?dāng)?shù)據(jù)也必須被刪除。為了實(shí)施這個(gè)規(guī)則,我們可以設(shè)置一個(gè) ForeignKeyConstraint 對(duì)象(請(qǐng)參見清單 7)。
清單 7. 設(shè)置數(shù)據(jù)關(guān)系。
Dim oDataRelation As DataRelation Dim oParentColumn As DataColumn Dim oChildColumn As DataColumn Dim oForeignKeyConstraint As ForeignKeyConstraint GetPaychecks() 'Manage both tables from within a DataSet object oDS.Tables.Add (oEmployeeDT) oDS.Tables.Add (oPayCheckDT) 'Retrieve PK, FK from the employee, paycheck tables oParentColumn = oEmployeeDT.Columns("ID") oChildColumn = oPayCheckDT.Columns("EmployeeID") 'Create DataRelation object to maintain relationship oDataRelation = New DataRelation("EmployeePaycheck", _oParentColumn, oChildColumn) oDS.Relations.Add (oDataRelation) 'Create ForeignKeyConstraint obj. to enforce delete oForeignKeyConstraint = New _ForeignKeyConstraint(oParentColumn, oChildColumn) oForeignKeyConstraint.DeleteRule = Rule.Cascade實(shí)際上,本文只是粗淺地探討了您在 VB6 和 .NET 中使用離線數(shù)據(jù)可以實(shí)現(xiàn)的操作。由于 Microsoft 的數(shù)據(jù)訪問(wèn)技術(shù)正趨向于廣泛使用離線數(shù)據(jù),因此了解如何使用離線數(shù)據(jù)對(duì)您未來(lái)的開發(fā)工作是至關(guān)重要的。
下載 408CARL1.ZIP
有關(guān) Hardcore Visual Basic 和 Pinnacle Publishing 的詳細(xì)信息,請(qǐng)?jiān)L問(wèn)其網(wǎng)站 http://www.pinpub.com/
注:這不是 Microsoft Corporation 的網(wǎng)站。Microsoft 對(duì)該網(wǎng)站的內(nèi)容不承擔(dān)責(zé)任。
本文是從 Hardcore Visual Basic 2004 年 8 月號(hào)轉(zhuǎn)載的。版權(quán)所有 2004,Pinnacle Publishing, Inc.(除非另行說(shuō)明)。保留所有權(quán)利。Hardcore Visual Basic 是 Pinnacle Publishing, Inc. 獨(dú)立發(fā)行的產(chǎn)品。未經(jīng) Pinnacle Publishing, Inc. 事先同意,不得以任何形式使用或復(fù)制本文的任何部分(評(píng)論文章中的簡(jiǎn)短引用除外)。要聯(lián)系 Pinnac
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的ADO与ADO.NET的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《中国编程挑战赛--资格赛》赛题及解答
- 下一篇: Baidu小窥(一)