ADO.NET 成功地提供了一组基类和接口,为通过其他类和接口访问关系型数据库提供了一种选择,因此,从 F# 中访问大多数关系型数据库不用太多的努力。我们已经讨论了大部分这样的类,或者至少这些类实现了它们打算提供的功能。表 9-2 汇总了其中的关键类。
表 9-2 ADO.NET 中的关键类
类 |
描述 |
System.Data.Common .DbConnection |
这个类表示对关系型数据库特定实例的连接,使用从它派生的类,指定想对哪个数据库执行执行查询。 |
System.Data.Common .DbCommand |
从这个基类派生的类,用于配置想对数据库执行哪种查询,是 SQL 查询,还是存储过程。 |
System.Data.Common .DbParameter |
这个类表示查询的参数。通常,参数化查询有利于在关系数据库中重用,使执行更有效。 |
System.Data.Common .DbDataReader |
从这个类派生的类,能够以线性方式访问查询的结果,可以快速访问结果。 |
System.Data.Common .DbDataAdapter |
这个类用于从关系型数据库的数据充填数据集(DataSet)类。 |
System.Data.DataSet |
这个类提供了数据库中内存中的表示,可以包含表和表之间的关系,不像本表中的其他类,这个类是具体的,可以直接使用。 |
在表 9-2 中的类,除了 System.Data.DataSet 类以外,都是抽象的,因此,必须使用类的具体实现。例如,这个示例演示了如何创建 System.Data.SqlClient.SqlConnection 类的实例,它是System.Data.Common.DbConnection 类的实现,它用于访问 SQL Server 数据库:
Use connection = newSqlConnection(connectionString)
如果想访问Oracle 数据库,只要把SqlConnection 类简单地替换成 OracleConnection。表 9-3 汇总了最流行的库,经及实现这些类的命名空间。这个表并不完整,因为提供程序的范围很广。
表 9-3 .NET 版本的数据库提供程序
命名空间 |
DLL |
描述 |
System.Data .Odbc |
System.Data.dll |
这个命名空间可以连接到任何提供了支持 ODBC (Open Database Connectivity,开放的数据连接)标准的数据库。大多数数据库都支持这个标准,但是通常应该避免使用,而应该使用更专门的驱动,因为它们会更有效。 |
System.Data .OleDb |
System.Data.dll |
OleDb 是基于 COM 标准的数据库的驱动,另外,大量关系型数据库都提供了支持该标准的驱动,但是,如果有可能,要使用更专门的驱动。这个命名空间通常用于连接到 Access 数据库或 Excel 电子表格,它们没有 .NET 版本的驱动。 |
System.Data .SqlClient |
System.Data.dll |
这是 Microsoft SQL Server 本地 .NET版本的驱动,它支持所有 SQL Server 的版本,是使用 SQL Server 的不二选择。书中示例都使用这个命名空间。 |
System.Data .OracleClient |
System.Data .OracleClient.dll |
这是 Oracle 数据库的本地 .NET 版本的提供程序,由 Microsoft 提供,随 .NET 框架一起发布。 |
Oracle.DataAccess .Client |
Oracle.DataAccess .Client.dll |
.NET 版本的 Oracle 数据提供程序(ODP.NET)是由 Oracle 开发的 .NET版本的数据库提供程序,在www.oracle.com/technology/software/tech/windows/odpnet。 |
IBM.Data.DB2 |
IBM.Data.DB2.dll |
这是由 IBM 开发的本地 .NET 版本的提供程序,随数据库发布。 |
MySql.Data .MySqlClient |
MySql.Data.dll |
这是由 MySQL 组开发的开源的本地 .NET 版本的提供程序。可以从 dev.mysql.com/downloads/connector/net 下载。 |
FirebirdSql.Data .FirebirdClient |
FirebirdSql.Data .FirebirdClient.dll |
这是开源数据库 Firebird 的本地提供程序,可以从 www.firebirdsql.org/index.php?op=files&id=netprovider 下载。 |
为演示如何使用其他的 .NET 版本的提供程序,连接到关系型数据库管理系统,现在给出一个例子,连接到 Firebird 的employee 示例数据库。运行这个示例,需要安装 Firebird 数据库引擎和 Firebird 的 .NET 版本的提供程序组件,可从 http://www.firebirdsql.org 下载;还需要在本地运行 Firebird 数据库服务。
open System.Configuration
open System.Collections.Generic
open System.Data
open FirebirdSql.Data.FirebirdClient
open System.Data.Common
open System
// firebird connection string
let connectionString =
@"Database=C:\ProgramFiles\Firebird\" +
@"Firebird_2_0\examples\empbuild\EMPLOYEE.FDB;"+
@"User=SYSDBA;"+ "Password=masterkey;" +
@"Dialect=3;"+ "Server=localhost";
// open firebird connection
let openFBConnection() =
letconnection = new FbConnection (connectionString)
connection.Open();
connection
// create a reader to read all theinformation
let openConnectionReader cmdString =
letconn = openFBConnection()
letcmd = conn.CreateCommand(CommandText = cmdString,
CommandType =CommandType.Text)
letreader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
reader
// read a row from the database and convertinto a dictionary
let readOneRow (reader: #DbDataReader) =
ifreader.Read() then
letdict = new Dictionary<string, obj>()
forx = 0 to (reader.FieldCount - 1) do
dict.Add(reader.GetName(x),reader.Item(x))
Some(dict)
else
None
// execute a database command creating asequence of the results
let execCommand cmdString =
Seq.generate
//This function gets called to open a conn and create a reader
(fun() -> openConnectionReader cmdString)
//This function gets called to read a single item in
//the enumerable for a reader/conn pair
(funreader -> readOneRow(reader))
(fun reader -> reader.Dispose())
// select all from the Employee‘s table
let employeeTable =
execCommand
"select* from Employee"
// print out the Employee‘s information
for row in employeeTable do
forcol in row.Keys do
printfn"%s = %O " col (row.Item(col))
前面示例的运行结果如下:
...
EMP_NO = 145
FIRST_NAME = Mark
LAST_NAME = Guckenheimer
PHONE_EXT = 221
HIRE_DATE = 02/05/1994 00:00:00
DEPT_NO = 622
JOB_CODE = Eng
JOB_GRADE = 5
JOB_COUNTRY = USA
SALARY = 32000
FULL_NAME = Guckenheimer, Mark
注意
只有非常小的变化,把 SQL Server AdventureWorks 的 contact 表转换成对Firebird employee 数据库表employee 的查询。