编辑16.1. 简介
Spring.NET用一个通用的工厂类来创建ADO.NET各种类型的对象,比如IDbConnection和IDbCommand等。这个工厂类和.NET 2.0中引入的工厂类(按:指DbProviderFactory)很相似,只是加入了一些必要的元数据,以支持Spring.NET中 DAO/ADO.NET框架所提供的功能如异常翻译等。工厂本身使用内嵌在Spring.Data程序集中的一个专用XML文件来配置,开发人员只需要关心如何使用该工厂类。目前该工厂类支持几个较为流行的数据库,通过扩展也可以支持新的数据库或修改原有的功能。Spring.NET还针对数据库应用定义了专门的Schema,可以简化数据库对象定义的配置工作。
与.NET 2.0中的工厂类相比,DbProvider的不足之处在于它只返回低层次的接口类型,而非System.Data.Common中的抽象基类。不过 DbProvider仍可以弥补.NET 2.0本身的一些不足。最明显的是在ADO.NET中,DbException包含的错误信息是远程过程调用的HRESULT,这样不直观的信息一般不是我们期望的。而Spring.NET可将错误码映射为统一的数据访问异常,并在其中包含引发错误的SQL语句。这样我们能很轻松的写出可移植的异常处理代码。另外,Spring.NET的DbParameter类也不像用诸如SqlClientFactory等强类型工厂创建的DbParameter一样包含那么多便利方法。不过,如果我们需要使用FCL中抽象或接口类型的数据库对象,仍可通过DbProvider类直接创建。最后,对FCL数据库类型的这种包装可以让我们很方便的与Spring.NET事务管理相集成——因为在用Spring.NET创建DbCommand对象时,DbCommand对象的Connection和Transaction属性已经根据事务调用环境预先设置好了。
顶部编辑16.1.1. IDbProvider和DbProviderFactory
IDbProvider接口如下所示,如果使用过.NET 2.0的DbProviderFactory类,就会发现这个接口与之相似。注意,Spring.NET的IDbProvider接口也适用于.NET 1.1。
public interface IDbProvider
{
IDbCommand CreateCommand();
object CreateCommandBuilder();
IDbConnection CreateConnection();
IDbDataAdapter CreateDataAdapter();
IDbDataParameter CreateParameter();
string CreateParameterName(string name);
IDbMetadata DbMetadata
{
get;
}
string ConnectionString
{
set;
get;
}
string ExtractError(Exception e);
bool IsDataAccessException(Exception e);
}
ExtractError方法用于返回一个错误信息,在将异常翻译为DAO异常时会用到该信息。IsDataAccessException方法用于在.NET 1.1中判断抛出的异常是否与特定的数据库有关,因为.NET 1.1没有为数据库异常定义公共基类。
DbProviderFactory类利用给定的Provider名称创建IDbProvider对象。在为IDbProvider对象设置了连接字符串以后,就可以用它来创建IDbConnection对象。Provider名称和对应的数据库如下所示。
- SqlServer-1.1:Microsoft SQL Server,provider V1.0.5000.0,用于.NET框架V1.1。
- SqlServer-2.0(System.Data.SqlClient的别名):Microsoft SQL Server,provider V2.0.0.0,用于.NET框架V2.0。
- OleDb-1.1:OleDb,provider V1.0.5000.0,用于.NET框架V1.1。
- OleDb-2.0(System.Data.OleDb的别名):OleDb,provider V2.0.0.0,用于.NET框架V2.0。
- OracleClient-2.0(System.Data.OracleClient的别名):Oracle,Microsoft provider V2.0.0.0。
- OracleODP-2.0(System.DataAccess.Client的别名):Oracle, Oracle provider V2.102.2.20。
- MySql:MySQL, MySQL provider 1.0.7.3007(按:Spring.NET的当前版本(1.1 Preview3)需要MySqlConnector 1.0.7.30072,您可以从MySql的网站上单独下载,当然您也可以修改Spring.Data以使用1.08 RC或5.02beta版。)
DbProviderFactory的用法如下所示:
IDbProvider dbProvider = DbProviderFactory.GetDbProvider("System.Data.SqlClient");
Provider对象都定义在内嵌的程序集内嵌资源assembly: //Spring.Data/Spring.Data.Common/dbproviders.xml中(按:参见src\Spring\ Spring.Data\Data\Common\dbproviders.xml文件)。未来会加入对其它数据库的支持。目前因陋就简,我们倒是有一个方法可以添加新的Provider,或者为Provider对象应用Spring.NET的其它功能如AOP通知等,方法是将 DbProviderFactory的DBPROVIDER_ADDITIONAL_RESOURCE_NAME属性设置为包含其它 IDbProvider对象定义的资源路径。该属性的默认值是file://dbProviders.xml。将来会用 App.config/web.config中的自定义配置节点来代替这一方法。
顶部
编辑16.1.2. XML配置
在配置文件中定义DbProvider的方法如下,一般我们会用它来设置AdoTemplate对象的DbProvider属性。(按:注意 objects节点需要引用命名空间xmlns:d="http://www.springframework.net/database"。)
<objects xmlns='http://www.springframework.net'
xmlns:d="http://www.springframework.net/database">
<d:dbProvider id="DbProvider"
provider="System.Data.SqlClient"
connectionString="Data Source=(local);Database=Spring;User ID=springqa;Password=springqa;Trusted_Connection=False"/>
<object id="adoTemplate" type="Spring.Data.AdoTemplate, Spring.Data">
<property name="DbProvider" ref="DbProvider"/>
</object>
</objects>
要使用上面的配置语法,还需要在主程序配置文件中注册一个自定义命名空间。如下面代码所示,注意其中只加入了parsers及相关的节点处理器:
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="parsers" type="Spring.Context.Support.ConfigParsersSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<parsers>
<parser namespace="http://www.springframework.net/database"
type="Spring.Data.DatabaseConfigParser, Spring.Data"
schemaLocation="assembly://Spring.Data/Spring.Data/spring-database.xsd" />
</parsers>
</spring>
</configuration>
顶部编辑16.1.3.管理连接字符串
在Spring.NET中,有几种方法可用于管理连接字符串。
第一种是使用IoC容器的属性替换功能,参见:4.9.1节,PropertyPlaceholderConfigurer类。这样我们可以在配置文件中使用变量名作为占位符,并由PropertyPlaceholderConfigurer对象统一管理变量的值。下面的例子将连接字符串参数化了,当然也可以直接使用完整的字符串。
请看下面的例子:
<configuration>
<configSections>
<sectionGroup name="spring">
<section name='context' type='Spring.Context.Support.ContextHandler, Spring.Core'/>
</sectionGroup>
<section name="databaseSettings" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<spring>
<context>
<resource uri="Aspects.xml" />
<resource uri="Services.xml" />
<resource uri="Dao.xml" />
</context>
</spring>
<!-- These properties are referenced in Dao.xml -->
<databaseSettings>
<add key="db.datasource" value="(local)" />
<add key="db.user" value="springqa" />
<add key="db.password" value="springqa" />
<add key="db.database" value="Northwind" />
</databaseSettings>
</configuration>
在Dao.xml文件中定义的DbProvider对象引用了上面的连接字符串,如下:
<objects xmlns='http://www.springframework.net'
xmlns:d="http://www.springframework.net/database">
<d:dbProvider id="DbProvider"
provider="System.Data.SqlClient"
connectionString="${db.datasource};Database=${db.database};User ID=${db.user};Password=${db.password};Trusted_Connection=False"/>
<object id="adoTemplate" type="Spring.Data.AdoTemplate, Spring.Data">
<property name="DbProvider" ref="DbProvider"/>
</object>
</objects>
TODO: The second option is to use a custom schema specific to your database. The case of using SqlServer is shown below.
顶部