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技巧吧。