翻译《Enterprise Library Guide》基本数据访问

2023/7/6 10:13:31

一些简单的介绍

当你在企业级应用开发中处理数据时,这些数据大多来自某种关系型数据库,访问的方式大多使用微软ADO.NET组件进行。数据访问应用程序块作为企业库中广泛被使用的组件,我们本章决定先介绍数据访问应用程序块。

到目前为止,来自世界数以百万计的.NET企业级应用开发采用数据访问程序块,为什么呢?因为它可以很容易地实现最常用的数据访问操作,而无需编写重复的代码,你不用担心数据库类型的变化,它适用于任何类型的数据库操作,只需要一个数据访问模块,就可以使用相同的代码访问不同类型的数据库,你不必担心参数和数据访问方式的不同,这一切的一切,企业库帮你完成。

这意味着,在你的应用程序中很容易切换不同类型的数据库,而不必重写代码、重新编译和重新部署。在不影响业务逻辑的情况下,管理员和操作员可以部署目标数据库到不同的服务器,甚至切换到不同的数据库(如从Oracle迁移到Microsoft SQL Server 或反之)。在目前的版本中,数据访问应用程序块包可以访问你SQL Server和SQL Server精简版的数据库,同时也支持Oracle数据库,但不赞成在此版本中使用,也有对第三方数据库的支持,例如:IBM DB2,MySQL和甲骨文公司(ODP.NET),PostgreSQL,SQLite数据库,欲了解更多信息,请参阅企业库开源社区。

使用数据访问应用程序块时,它屏蔽了不同的数据库所使用的语法的差异,从而有利于不同数据库类型之间的切换。

什么是数据访问应用程序块?

数据访问应用程序块抽象您使用的实际的数据库类型,并公开了一系列的方法,让您轻松访问数据库执行常见任务,它对存储过程的提供了完整的支持,使用参数化SQL语句。当你填充DataSet时,您只需创建相应的数据库类型的一个对象,使用它得到适当的命令对象(例如DbCommand),并通过ExecuteDataSet方法,不需要创建DataAdapter和调用Fill方法。 ExecuteDataset方法帮你管理连接,并进行填充DataSet数据集。以类似的方式,数据库对象允许你获得一个DataReader,直接执行命令,并从DataSet更新数据库,本程序块还支持事务,帮助您管理多个操作,可提交,如果发生错误,也可回滚。

除了比较常见的方法,数据访问块还提供了对异步数据库访问的支持,并提供了异步返回数据的能力,适用于客户端异步处理的需求,例如:语言集成查询(LINQ)。然而,数据访问程序块并不打算成为一个对象/关系映射(O/ RM)解决方案,但它支持映射​​相关参数对象的属性和关系数据,并没有实现一个完整的O / RM模型的解决方案。 如果你想要一个对象/关系映射的解决方案,你应该考虑使用微软官方提供的ADO.NET实体框架,它已被集成到Visual Studio开发环境中。

使用数据访问块,主要优点是它提供了访问数据的统一方式,让你很容易在不同的源数据库中切换。在大多数情况下,除非你的代码需要使用特定数据库的某个优势,否则你唯一需要改变的就是配置文件中的连接字符串,您不必改变指定查询方式(如SQL语句或存储过程),创建和填充参数或返回值处理,这也意味着降低了对应用程序的测试要求,因为不需要针对不同的数据库类型进行单元测试。

如何使用数据访问块?

在您开始使用数据访问块之前,你必须将它添加到您的应用程序中,您可以通过配置文件中的连接字符串,指定访问块要使用的数据库,然后你就可以在你的代码中创建这些数据库的实例,并用它们来读取和写入数据。

将数据访问应用程序块添加到你的项目中

使用的数据访问块的第一个步骤是引用程序集EnterpriseLibrary.Data.dll到您的项目,然后添加对Microsoft.EnterpriseLibrary.Data命名空间的引用,如果你计划使用SQL CE数据库块,你需要引用EnterpriseLibrary.Data.SqlCe.dll程序集,并添加命名空间。

配置访问块和引用所需的程序集

使用的数据访问块的下一个步骤是配置您需要访问的数据库,如果当前应用程序是窗体和控制台,则使用App.config文件配置,如果是网站或者Asp.net应用程序,则使用Web.config文件配置,无论是App.config还是Web.config,它们的标准都是配置节点。你也可以使用其它配置文件来存储数据库连接字符串,下面是一个示例配置文件,配置连接字符串和默认的数据库。

xml version="1.0"?> <configuration> <configSections> <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data" requirePermission="true" /> </configSections> <dataConfiguration defaultDatabase="ExampleDatabase"/> <connectionStrings> <add name="ExampleDatabase" connectionString="..." providerName="System.Data.SqlClient" /> <add name="AsyncExampleDatabase" connectionString="..." providerName="System.Data.SqlClient" /> </connectionStrings> </configuration>

另外,您可以使用企业库配置工具来配置这些设置如果您正在使用Oracle数据库,你可以使用甲骨文公司提供的数据提供程序,这就需要你引用或添加System.Data.OracleClient.dll组件。但是,请记住,在4.0版本的.NET框架中,OracleClient被提供商弃用。虽然的OracleClient提供商的支持包含在企业库6.0版本中,但为了适应未来的发展,你应该考虑选择不同的数据库实现类和Oracle驱动程序。同时你需要在你的项目中引用下面的两个命名空间:

using Microsoft.Practices.EnterpriseLibrary.Data using Microsoft.Practices.EnterpriseLibrary.Data.Sql

创建数据库实例

您可以使用多种不同的方法来获得您要访问数据库的数据库实例,可参见本指南第一章的简介部分,该部分向介绍了实例化企业库对象的不同方法。你可以使用最简单的方法调用CreateDefault方法或使用DatabaseProviderFactory类,如下所示:

// Configure the DatabaseFactory to read its configuration from the .config file DatabaseProviderFactory factory = new DatabaseProviderFactory();

<span style="color: green;">// Create the default Database object from the factory.
// The actual concrete type is determined by the configuration settings.
</span><span style="color: #2b91af;">Database </span>defaultDB = factory.CreateDefault();

<span style="color: green;">// Create a Database object from the factory using the connection string name.
</span><span style="color: #2b91af;">Database </span>namedDB = factory.Create(<span style="color: #a31515;">"ExampleDatabase"</span>);

下面的代码片段显示了该项目中的app.config文件中的配置设置:

xml version="1.0"?> <configuration> <configSections> <section name="dataConfiguration" type="..."/> </configSections> <dataConfiguration defaultDatabase="ExampleDatabase"/> <connectionStrings> <add name="ExampleDatabase" connectionString="..." providerName="System.Data.SqlClient" /> <add name="AsyncExampleDatabase" connectionString="..." providerName="System.Data.SqlClient" /> </connectionStrings> </configuration>

上面的代码展示了如何得到一个默认的数据库实例和已命名数据库实例(使用连接字符串中的名称)。使用默认的数据库是一个有用的方法,因为你可以通过编辑配置简单地改变数据库,而无需重新编译或重新部署应用程序。 虽然你需要dataConfiguration配置节部分,但是,如果您要使用CreateDefault方法,它并不需要这个配置节部分,如果你使用Create方法,Create方法直接读取连接字符串。

某些功能仅适用于特定的数据库的具体类型。例如,ExecuteXmlReader方法是仅适用于的SqlDatabase类。如果你想使用这些功能,你必须投实例的数据库类型相应的具体类型。下面的代码创建一个SqlDatabase的实例。您可能需要把数据库类型转换为特定类型,如SqlDatabase访问特定功能​​。你应该检查返回的引用在使用它之前不为null。

// Create a SqlDatabase object from configuration using the default database. SqlDatabase sqlServerDB = factory.CreateDefault() as SqlDatabase;

作为DatabaseProviderFactory的替代类,你可以使用静态的DatabaseFactory来创建你的数据库实例。你必须调用SetDatabaseProviderFactory的方法,从配置文件中设置的默认数据库。

DatabaseFactory.SetDatabaseProviderFactory(factory, false); defaultDB = DatabaseFactory.CreateDatabase("ExampleDatabase");

<span style="color: green;">// Uses the default database from the configuration file.
</span>sqlServerDB = <span style="color: #2b91af;">DatabaseFactory</span>.CreateDatabase() <span style="color: blue;">as </span><span style="color: #2b91af;">SqlDatabase</span>;

除了使用配置来定义您将使用的数据库,数据访问模块允许你直接从数据库类继承,如下所示,所有你需要做的就是提供一个连接字符串,指定适当的ADO.NET数据提供程序类型(如SqlClient的)。

// Assume the method GetConnectionString exists in your application and // returns a valid connection string. string myConnectionString = GetConnectionString(); SqlDatabase sqlDatabase = new SqlDatabase(myConnectionString);

示例应用程序

现在,你有可以使用一个数据库对象准备执行任何任务,在本章的剩余部分,我们会告诉你如何用它来执行各种任务。您可以下载一个示例应用程序(一个简单的基于控制台的应用程序),该示例程序演示了所有的场景。

读取多行数据

在.NET程序中,其中最常见的操作就是在数据库中读取多行数据,您通常访需要DataReader一个DataReader实例,或将它们存储在一个DataTable(通常在您创建一个DataSet)。在本节中,我们将着眼于使用ExecuteReader方法,返回一个DataReader,在本章后面,您将看到如何使用DataSet数据访问方法。

当然,在数据访问中除了DataReader和DataTable外,还有最新的技术可以选择: Entity Framework and LINQ to SQL

使用不带参数的查询读取多行数据

简单查询,一般使用 不带任何参数的SQL 语句或存储的过程,可以使用接受一个CommandType和 SQL 语句或存储的过程的名称作为字符串重载来执行。 下面的代码演示最简单的方法,对于存储过程,您也可以省略命令类型参数。默认值是 CommandType.StoredProcedure (不同于 ADO.NET 中,默认情况下是 CommandType.Text)。

// Call the ExecuteReader method by specifying just the stored procedure name. using (IDataReader reader = namedDB.ExecuteReader("MyStoredProcName")) { // Use the values in the rows as required. }

要使用内嵌的SQL语句,你必须指定适当的CommandType值,如下所示:

// Call the ExecuteReader method by specifying the command type // as a SQL statement, and passing in the SQL statement. using (IDataReader reader = namedDB.ExecuteReader(CommandType.Text, "SELECT TOP 1 * FROM OrderList")) { // Use the values in the rows as required - here we are just displaying them. DisplayRowValues(reader); }

使用参数数组查询多行数据

虽然在某些情况下,你可以使用简单的无参数的存储过程和SQL语句,但最常见的还是输入一些查询参数进行查询,你可以将参数值封装成数组传递个存储过程和SQL语句,需要注意的是这个数组中的参数值必须依次有序,因为你没有指定参数名称,所以只能通过顺序区分它们。下面的代码演示执行一个存储的过程,采用单个字符串参数。

// Call the ExecuteReader method with the stored procedure // name and an Object array containing the parameter values. using (IDataReader reader = defaultDB.ExecuteReader("ListOrdersByState", new object[] { "Colorado" })) { // Use the values in the rows as required - here we are just displaying them. DisplayRowValues(reader); }

使用命名参数读取多行数据

在前面提供的数组类型参数化,虽然很方便也很高效,但有一些限制。它不允许您指定参数的方向 (如输入或输出)和数据类型 — — 这可能是一个问题,如果一个参数的数据类型并不完全匹配 (或不能隐式转换为) ,即无法正确转换。如果您为查询创建命名参数化,你可以指定有关参数的类型和参数的方向。

若要使用命名的参数定义的类型,您必须获得一个用于执行查询并操纵其参数的命令对象。数据访问块轻松创建和使用命令对象的两种方法: GetSqlStringCommand 和 GetStoredProcCommand。这些方法返回相应命令类的实例作为提供程序的 DbCommand 类型。

创建相应类型的命令后,可以使用许多不同的数据库方法来操作参数集合。你可以通过指定参数特定的方向的AddInParameter或AddOutParameter的方法,或通过使用 AddParameter方法并提供ParameterDirection 参数的值。也可以使用GetParameterValue 和SetParameterValue方法获得和设置现有参数的值。

下面的代码演示创建一个命令,添加一个输入参数,并执行一个SQL语句和存储过程。请注意代码如何指定参数的名称,数据类型,以及参数值。

// Read data with a SQL statement that accepts one parameter prefixed with @. string sqlStatement = "SELECT TOP 1 * FROM OrderList WHERE State LIKE @state"; // Create a suitable command type and add the required parameter. using (DbCommand sqlCmd = defaultDB.GetSqlStringCommand(sqlStatement)) { defaultDB.AddInParameter(sqlCmd, "state", DbType.String, "New York"); // Call the ExecuteReader method with the command. using (IDataReader sqlReader = namedDB.ExecuteReader(sqlCmd)) { DisplayRowValues(sqlReader); } }

<span style="color: green;">// Now read the same data with a stored procedure that accepts one parameter.
</span><span style="color: blue;">string </span>storedProcName = <span style="color: #a31515;">"ListOrdersByState"</span>;
<span style="color: green;">// Create a suitable command type and add the required parameter.
</span><span style="color: blue;">using </span>(DbCommand sprocCmd = defaultDB.GetStoredProcCommand(storedProcName))
{
   defaultDB.AddInParameter(sprocCmd, <span style="color: #a31515;">"state"</span>, DbType.String, <span style="color: #a31515;">"New York"</span>);
   <span style="color: green;">// Call the ExecuteReader method with the command.
   </span><span style="color: blue;">using </span>(IDataReader sprocReader = namedDB.ExecuteReader(sprocCmd))
   {
    DisplayRowValues(sprocReader);
   }
}

每当你使用SQL字符串语句时间,你应该仔细考虑,如果你需要验证一个可能的SQL注入攻击。

检索数据作为对象

现代编程技术,通常将数据作为对象,这种方法是有用的,如果你在应用层传递数据使用数据传输对象(DTO),数据接入层采用ORM技术,或想利用新的客户端数据查询技术,如LINQ。 如果你需要在网络上使用数据,可以考虑使用WCF数据服务。

数据访问块,本身就不是一个O/RM的解决方案,但它能让你使用SQL语句或存储过程作为查询,提取数据,并将已返回的数据作为实现IEnumerable接口的对象,这可以让你执行查询并转换成对象。

关于数据访问器

该模块提供了两个执行查询的方式:SprocAccessor和SqlStringAccessor的核心类。您可以通过数据库类创建并执行ExecuteSprocAccessor和ExecuteSqlAccessor方法,或创建一个新的访问,然后调用其Execute方法,在该行的值映射从数据库返回对象的属性,它会返回给客户端代码,下图显示了总体过程。

EnterpriseLibraryAccessData

由于时间关系 ,翻译未完续,每天翻译一点点,进步一点点,希望对您有所帮助,谢谢!