Create the connection Dim factory As New MyAppConnectionFactory Dim conn As IDbConnection conn = factory.CreateConnection(connString)' Create the command Dim cmd As IDbCommand = conn.CreateCommand(query) 一旦你得到了一個連接對象,你就可以以database-agnostic的方式來創建和執行一個命令了,而不管使用的數據源是什么。你可以使用CreateCommand方法并通過IDbCommand接口來引用命令。然后,你可以用IDbCommand接口上的ExecuteReader方法或ExecuteNonQuery方法來執行命令。假如你用ExecuteReader,你就可以得到一個data reader并可以用IDataReader接口來對它進行一般的訪問了。 你不能用一個通用的數據庫編程模式來填充一個DataSet對象。實際上,你不能像創建一個命令那樣以一種間接的方式來創建data adapter對象。原因就是,在有些情況下,data adapter不同于命令對象,它可以在內部隱含地創建一個連接。然而,它必須以一種強類型的方式工作,而且必須知道基本的數據庫服務器是什么。 2. 運用字符串來串行化擴展的屬性
用于SQL Server的.NET數據提供者(data provider)使用了數據庫提供的XML擴展名,并提供了一個額外的方法(ExecuteXmlReader)來執行查詢。命令對象上的所有的執行者(例如ExecuteReader和ExecuteScaler)都采用不同的方法來得到結果集。ExcecuteReader通過一個托管指針(managed cursor)(data reader)來返回數據,而ExecuteScaler返回結果集中的第一個值,把它作為一個標量值。ExecuteXmlReader執行查詢,并返回已經綁定到一個XmlTextReader對象的基于XML的輸出流。通過這種方式,你就不需要做額外的工作來以XML的方式加工數據了。要實現這一點,查詢字符串必須返回XML數據。對SQL Server來說,當查詢字符串包含一個FOR XML子句時,就可以實現它。盡管這只是一種可能。 一個不太為人所知的情況是,要使ExecuteXmlReader工作,讓結果集包含XML數據就足夠了。下面的查詢方法很好,只要列包含XML格式的文本就行(見圖1):SELECT data FROM table WHERE key=1
Dim view As DataView view = New DataView(table) view.Sort = "orderid" Dim index As Integer = view.Find(10248) Dim row As DataRow = view(index).Row Find方法運用了視圖的當前索引,并將指定的值(或多個值)與形成當前索引的字段匹配起來。在前面的代碼中,值10248與列orderid匹配。假如Sort屬性為空,且DataTable對象有一個主鍵,那么就運用主鍵中的列。Find方法返回的是相匹配的第一行的基于0的位置的值。 假如你想返回多個記錄,可以用FindRows的演變形式: view.Sort = "orderid, discount" Dim keys(1) As Object keys(0) = 10248 keys(1) = 0 Dim row As DataRow = _ view(view.Find(keys)).Row 前面的代碼可以讓你通過運用Find的重載方法(帶有一組對象)來匹配多個列的值。 6. 盡可能用預先排序的數據
ADO.NET并沒有為得到并治理schema信息提供一個完全的對象模式。你應該用ActiveX Data Objects Extensions for Data Definition Language and Security (ADOX)或用每個數據庫提供的本地功能來得到并改變Schema信息。ADOX是ADO對象的一個擴展,它包括用來創建和修改Schema的對象。你可以編寫適用于各種數據源的代碼(不管本地語法有什么不同),因為ADOX是治理schema的一個基于對象的方法。 你可以用一個data reader對象來讀(不是設置)簡單的schema信息。所有的data reader類(OleDbDataReader、SqlDataReader、OracleDataReader)都提供了一個GetSchemaTable方法,該方法可以讀取查詢到的列的元數據信息。GetSchemaTable返回一個DataTable對象(格式是每列一行)和固定的一組包含信息的列。返回的元數據可以分成三類:列元數據、數據庫特征和列屬性。返回的列可以是AllowDBNull、IsAutoIncrement、ColumnName、IsEXPression、IsReadonly和NumericPrecision等。在MSDN資料中有完整的列表(見附加資源)。 在調用ExecuteReader時,假如你執行KeyInfo命令,那么GetSchemaTable方法就可以返回更精確的數據。你可以將KeyInfo行為同缺省的行為結合起來,執行一個單獨的命令并得到schema和數據:
根據查詢的語法,你可以返回多個結果集。缺省情況下,data reader是位于第一個結果集上的。你可以用Read方法在當前結果集中滾動查看記錄。在找到最后一個記錄時,Read方法返回false,不再繼續讀取。你應該用NextResult方法轉移到下一個結果集。假如沒有更多的需要讀的結果集了,那么該方法返回false。下面的代碼說明了如何在所有返回的結果集中訪問所有的記錄: Dim reader As SqlDataReader cmd.Connection.Open() reader = cmd.ExecuteReader() Do ' Move through the first resultset While reader.Read() ' access the row End While Loop While reader.NextResult() reader.Close() cmd.Connection.Close() 當你讀一個行的內容時,可以通過索引或名稱來識別列。運用索引可以更快,因為提供者可以直接進入到緩沖器中。假如你指定列名,提供者就用GetOrdinal方法將名稱轉換成相應的索引,然后執行基于索引的訪問。注重,對于SQL Server data reader來說,所有的GetXXX方法實際上都調用了相應的GetSqlXXX方法。對于Oracle data reader來說,情況是類似的,本地數據總是被寫進.NET Framework類型中。OracleDataReader類為它自己的內部類型提供了一組私有的GetXXX方法。這些方法包括GetOracleBFile、GetOracleBinary和GetOracleDateTime等。相反,OLE DB和ODBC readers只有單獨的一組get方法。 .NET Framework 1.1版通過添加方法HasRows擴展了data readers的編程接口,該方法返回一個Boolean值來說明是否有很多行需要讀。(這是ASP.NET 1.0的一個不足之處。)然而,該方法并沒有告訴我們有效的行的數量。同樣,也沒有方法或技巧使我們提前知道已經返回了多少結果集。 在Oracle數據庫編程中,一個查詢或一個存儲過程返回的多個結果集是通過多個REF CURSOR對象處理的。有多少結果集,你就必須將多少輸出參數同命令關聯起來,以便NextResult方法可以用于Oracle數據庫。在命令文本中,一個ADO.NET結果集同一個Oracle REF CURSOR是一致的。輸出參數名必須與指針名匹配,它們的類型必須是OracleType.Cursor。例如,假如要運行的存儲過程(或命令文本)引用了兩個指針(Employees和Orders),那么下面的代碼就說明了如何進行設置以返回兩個結果集: Dim p1 As OracleParameter p1 = cmd.Parameters.Add("Employees", OracleType.Cursor) p1.Direction = ParameterDirection.Output Dim p2 As OracleParameter p2 = cmd.Parameters.Add("Orders", OracleType.Cursor) p2.Direction = ParameterDirection.Output 在上面的代碼中,cmd是一個OracleCommand對象,它指向一個命令或一個存儲過程。它執行代碼,創建了兩個REF CURSOR,稱為Employees和Orders。REF CURSOR的名稱和ADO.NET輸出參數的名稱必須匹配。 ADO.NET對象模式包含兩個主要的部分——托管提供者和database-agnostic的容器類,如DataSet。托管提供者是數據源連接器的新類型;它們代替了基于COM的OLE DB提供者。到我寫這篇文章時為止,只有少數幾個托管提供者來連接商業DBMS。.NET Framework 1.1版只包含幾個本地提供者——用于SQL Server、Oracle和所有OLE DB的提供者和ODBC驅動程序。第三方的供給商也支持MySQL并為Oracle提供了可供選擇的提供者。 ADO.NET看起來類似于ADO,而且托管提供者在結構上同OLE DB提供者也是可以相比的。除了這些相似點外,在ADO.NET中進行有效的編程還需要一套新的技巧和好的方法。在大多數情況下,你可以通過編寫代碼得到很多技巧,并積累對象模式方面的經驗。當你在進一步研究ADO.NET編程時,記住我在本文中所講的這10個ADO.NET技巧吧。