683 lines
28 KiB
XML
683 lines
28 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!--
|
|
/*
|
|
* Copyright 2002-2008 the original author or authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
-->
|
|
<chapter version="5" xml:id="dbprovider" xmlns="http://docbook.org/ns/docbook"
|
|
xmlns:ns6="http://www.w3.org/1999/xlink"
|
|
xmlns:ns5="http://www.w3.org/1998/Math/MathML"
|
|
xmlns:ns4="http://www.w3.org/2000/svg"
|
|
xmlns:ns3="http://www.w3.org/1999/xhtml"
|
|
xmlns:ns="http://docbook.org/ns/docbook">
|
|
<title>DbProvider</title>
|
|
|
|
<section xml:id="dbprovider-introduction">
|
|
<title>Introduction</title>
|
|
|
|
<para>Spring provides a generic factory for creating ADO.NET API artifacts
|
|
such as <code><literal>IDbConnection</literal></code> and
|
|
<code><literal>IDbCommand</literal></code>. The factory API is very
|
|
similar to the one introduced in .NET 2.0 but adds extra metadata needed
|
|
by Spring to support features provided by its DAO/ADO.NET framework such
|
|
as error code translation to a DAO exception hierarchy. The factory itself
|
|
is configured by using a standard Spring XML based configuration file
|
|
though it is unlikely you will need to modify those settings yourself, you
|
|
only need be concerned with using the factory. Out of the box several
|
|
popular databases are supported and an extension mechanism is available
|
|
for defining new database providers or modifying existing ones. A custom
|
|
database namespace for configuration aids in making terse XML based
|
|
declarations of Spring's database objects you wish to use.</para>
|
|
|
|
<para>The downside of Spring's factory as compared to the one in .NET 2.0
|
|
is that the types returned are lower level interfaces and not the abstract
|
|
base classes in System.Data.Common. However, there are still 'holes' in
|
|
the current .NET 2.0 provider classes that are 'plugged' with Spring's
|
|
provider implementation. One of the most prominent is the that the top
|
|
level DbException exposes the HRESULT of the remote procedure call, which
|
|
is not what you are commonly looking for when things go wrong. As such
|
|
Spring's provider factory exposes the vendor sql error code and also maps
|
|
that error code onto a consistent data access exception hierarchy. This
|
|
makes writing portable exception handlers much easier. In addition, the
|
|
DbParameter class doesn't provide the most common convenient methods you
|
|
would expect as when using say the SqlServer provider. If you need to
|
|
access the BCL provider abstraction, you still can through Spring's
|
|
provider class. Furthermore, a small wrapper around the standard BCL
|
|
provider abstraction allows for integration with Spring's transaction
|
|
management facilities, allowing you to create a DbCommand with its
|
|
connection and transaction properties already set based on the transaction
|
|
calling context.</para>
|
|
</section>
|
|
|
|
<section xml:id="dbprovider-dbprovider">
|
|
<title>IDbProvider and DbProviderFactory</title>
|
|
|
|
<para>The <code><literal>IDbProvider</literal></code> API is shown below
|
|
and should look familiar to anyone using .NET 2.0 data providers. Note
|
|
that Spring's DbProvider abstraction can be used on .NET 1.1 in addition
|
|
to .NET 2.0</para>
|
|
|
|
<programlisting language="csharp">public interface IDbProvider
|
|
{
|
|
<classname>IDbCommand</classname> CreateCommand();
|
|
|
|
object CreateCommandBuilder();
|
|
|
|
<classname>IDbConnection</classname> CreateConnection();
|
|
|
|
<classname>IDbDataAdapter</classname> CreateDataAdapter();
|
|
|
|
<classname>IDbDataParameter</classname> CreateParameter();
|
|
|
|
string CreateParameterName(string name);
|
|
|
|
string CreateParameterNameForCollection(string name);
|
|
|
|
<classname>IDbMetadata</classname> DbMetadata
|
|
{
|
|
get;
|
|
}
|
|
|
|
string ConnectionString
|
|
{
|
|
set;
|
|
get;
|
|
}
|
|
|
|
string ExtractError(Exception e);
|
|
|
|
bool IsDataAccessException(Exception e);
|
|
|
|
}</programlisting>
|
|
|
|
<para>ExtractError is used to return an error string for translation into
|
|
a DAO exception. On .NET 1.1 the method IsDataAccessException is used to
|
|
determine if the thrown exception is related to data access since in .NET
|
|
1.1 there isn't a common base class for database exceptions.
|
|
CreateParameterName is used to create the string for parameters used in a
|
|
CommandText object while CreateParameterNameForCollection is used to
|
|
create the string for a IDataParameter.ParameterName, typically contained
|
|
inside a IDataParameterCollection.</para>
|
|
|
|
<para>The class <literal>DbProviderFactory</literal> creates IDbProvider
|
|
instances given a provider name. The connection string property will be
|
|
used to set the IDbConnection returned by the factory if present. The
|
|
provider names, and corresponding database, currently configured are
|
|
listed below.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>SqlServer-1.1</literal> - Microsoft SQL Server,
|
|
provider V1.0.5000.0 in framework .NET V1.1</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SqlServer-2.0</literal> (aliased to
|
|
<literal>System.Data.SqlClient</literal>) - Microsoft SQL Server,
|
|
provider V2.0.0.0 in framework .NET V2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SqlServerCe-3.1</literal> - Microsoft SQL Server
|
|
Compact Edition, provider V9.0.242.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SqlServerCe-3.5.1</literal> (aliased to
|
|
<literal>System.Data.SqlServerCe</literal>) - Microsoft SQL Server
|
|
Compact Edition, provider V3.5.1.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>OleDb-1.1</literal> - OleDb, provider V1.0.5000.0 in
|
|
framework .NET V1.1</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>OleDb-2.0</literal> (aliased to
|
|
<literal>System.Data.OleDb</literal>) - OleDb, provider V2.0.0.0 in
|
|
framework .NET V2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>OracleClient-2.0</literal> (aliased to
|
|
<literal>System.Data.OracleClient</literal>) - Oracle, Microsoft
|
|
provider V2.0.0.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>OracleODP-2.0</literal> (aliased to
|
|
<literal>System.DataAccess.Client</literal>) - Oracle, Oracle provider
|
|
V2.102.2.20 (Oracle 10g)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>OracleODP-11-2.0</literal> - Oracle, Oracle provider
|
|
V2.111.7.20 (Oracle 11g)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql</literal> - MySQL, MySQL provider 1.0.10.1</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql-1.0.9</literal> - MySQL, MySQL provider
|
|
1.0.9</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql-5.0</literal> - MySQL, MySQL provider
|
|
5.0.7.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql-5.0.8.1</literal> - MySQL, MySQL provider
|
|
5.0.8.1</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql-5.1</literal> - MySQL, MySQL provider
|
|
5.1.2.2</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql-5.1.4</literal> - MySQL, MySQL provider
|
|
5.1.2.2</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql-5.2.3</literal> - MySQL, MySQL provider
|
|
5.2.3.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql-6.1.3</literal> - MySQL, MySQL provider
|
|
6.1.3.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MySql-6.2.2</literal> (aliased to
|
|
<literal>MySql.Data.MySqlClient</literal>) - MySQL, MySQL provider
|
|
6.2.2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Npgsql-1.0</literal> - Postgresql provider 1.0.0.0 (and
|
|
1.0.0.1 - were build with same version info)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Npgsql-2.0-beta1</literal> - Postgresql provider
|
|
1.98.1.0 beta 1</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Npgsql-2.0</literal> - Postgresql provider
|
|
2.0.0.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>DB2-9.0.0-1.1</literal> - IBM DB2 Data Provider 9.0.0
|
|
for .NET Framework 1.1</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>DB2-9.0.0-2.0</literal> (aliased to
|
|
<literal>IBM.Data.DB2</literal>) - IBM DB2 Data Provider 9.0.0 for
|
|
.NET Framework 2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>DB2-9.1.0-1.1</literal> - IBM DB2 Data Provider 9.1.0
|
|
for .NET Framework 1.1</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>DB2-9.1.0.2</literal> (aliased to
|
|
<literal>IBM.Data.DB2.9.1.0</literal>) - IBM DB2 Data Provider 9.1.0
|
|
for .NET Framework 2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>iDB2-10.0.0.0</literal> - IBM iSeries DB2 Data Provider
|
|
10.0.0.0 for .NET Framework 2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SQLite-1.0.43</literal> - SQLite provider 1.0.43 for
|
|
.NET Framework 2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SQLite-1.0.44</literal> - SQLite provider 1.0.44 for
|
|
.NET Framework 2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SQLite-1.0.47</literal> - SQLite provider 1.0.47 for
|
|
.NET Framework 2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SQLite-1.0.56</literal> - SQLite provider 1.0.56 for
|
|
.NET Framework 2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SQLite-1.0.65</literal> (aliased to System.Data.SQLite)
|
|
- SQLite provider 1.0.65 for .NET Framework 2.0</para>
|
|
|
|
<note>
|
|
<para>The default parameter prefix used in SQLite is : and not @,
|
|
please write your SQL accordingly or define a provider definition
|
|
for SQLite.</para>
|
|
</note>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Firebird-2.1</literal> (aliased to
|
|
<literal>Firebird-2.1</literal>) - Firebird Server, provider V2.1.0.0
|
|
in framework .NET V2.0</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SybaseAse-12</literal> - Sybase ASE provider for ASE
|
|
12.x</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SybaseAse-15</literal> - Sybase ASE provider for ASE
|
|
15.x</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SybaseAse-AdoNet2</literal> - Sybase ADO.NET 2.0
|
|
provider for ASE 12.x and 15.x</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Odbc-1.1</literal> - ODBC provider V1.0.5000.0 in
|
|
framework .NET V1.1</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Odbc-2.0</literal> - ODBC provider V2.0.0.0 in
|
|
framework .NET V2</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Cache-2.0.0.1</literal> (aliased to
|
|
<literal>InterSystems.Data.CacheClient</literal>) - Cache provider
|
|
Version 2.0.0.1 in framework .NET V2</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<note>
|
|
<para>If your exact version of the database provider is not listed, you
|
|
can pick the general provider name, i.e.
|
|
<literal>MySql.Data.MySqlClient</literal>, and then perform an assembly
|
|
redirect in App.config. This will often be sufficient to upgrade to
|
|
newer versions. As shown below</para>
|
|
|
|
<programlisting><runtime>
|
|
|
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
|
|
<dependentAssembly>
|
|
<assemblyIdentity name="Npgsql"
|
|
publicKeyToken="5d8b90d52f46fda7"
|
|
culture="neutral"/>
|
|
<bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535
|
|
newVersion="2.0.0.0"/>
|
|
|
|
</dependentAssembly>
|
|
|
|
</assemblyBinding>
|
|
|
|
</runtime></programlisting>
|
|
</note>
|
|
|
|
<para>An example using DbProviderFactory is shown below</para>
|
|
|
|
<programlisting language="csharp"><classname>IDbProvider</classname> dbProvider = <classname>DbProviderFactory</classname>.GetDbProvider("System.Data.SqlClient");</programlisting>
|
|
|
|
<para>The default definitions of the providers are contained in the
|
|
assembly resource
|
|
<code>assembly://Spring.Data/Spring.Data.Common/dbproviders.xml</code>. If
|
|
the provider you want to use is not provided "out of the box" you can
|
|
provide additional definitions. To do this follow the format of object
|
|
definitions defined in the previously mentioned assembly resource.</para>
|
|
|
|
<para>From Spring 1.3.1 an on you can specify the additional Spring
|
|
IResource location where additional providers are defined within Spring's
|
|
XML configuration file. See the next section for an example.
|
|
Alternatively, you can set the public static property
|
|
DBPROVIDER_ADDITIONAL_RESOURCE_NAME in
|
|
<literal>DbProviderFactory</literal> to a Spring resource location. The
|
|
default value is <code>file://dbProviders.xml</code>. (That isn't a typo,
|
|
there is a difference in case with the name of the embedded
|
|
resource).</para>
|
|
|
|
<para>It may happen that the version number of an assembly you have
|
|
downloaded is different than the one listed above. If it is a point
|
|
release, i.e. the API hasn't changed in anyway that is material to your
|
|
application, you should add an assembly redirect of the form shown
|
|
below.</para>
|
|
|
|
<programlisting language="myxml"><dependentAssembly>
|
|
<assemblyIdentity name="MySql.Data"
|
|
publicKeyToken="c5687fc88969c44d"
|
|
culture="neutral"/>
|
|
<bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535"
|
|
newVersion="1.0.10.1"/>
|
|
</dependentAssembly></programlisting>
|
|
|
|
<para>This redirects any reference to an older version of the assembly
|
|
MySql.Data to the version 1.0.10.1.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>XML based configuration</title>
|
|
|
|
<para>Creating a DbProvider in Spring's XML configuration file is shown
|
|
below in the typical case of using it to specify the DbProvider property
|
|
on an AdoTemplate.</para>
|
|
|
|
<programlisting language="myxml"><objects xmlns='http://www.springframework.net'
|
|
xmlns:db="http://www.springframework.net/database">
|
|
|
|
<db:provider 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.Core.AdoTemplate, Spring.Data">
|
|
<property name="DbProvider" ref="DbProvider"/>
|
|
</object>
|
|
|
|
</objects></programlisting>
|
|
|
|
<para>If you need to register an additional IDbProvider defintions from
|
|
your own configuration file, set the attribute 'additonalDbProviders' to
|
|
the IResource location of those definitions. Examples of the format for
|
|
additional provider definitions can be found within the Spring.Data
|
|
assembly, location
|
|
<code>assembly://Spring.Data/Spring.Data.Common/dbproviders.xml</code>.
|
|
Open it up in Visual Studio or Reflector to see the contents of the
|
|
dbproviders.xml file.</para>
|
|
|
|
<programlisting language="myxml"><objects xmlns='http://www.springframework.net'
|
|
xmlns:db="http://www.springframework.net/database">
|
|
|
|
<emphasis role="bold"><db:additionalProviders resource="assembly://MyAssembly/MyAssembly.MyNamespace/AdditionalProviders.xml"/></emphasis>
|
|
|
|
<db:provider id="DbProvider"
|
|
provider="System.Data.SqlClient"
|
|
connectionString="Data Source=(local);Database=Spring;User ID=springqa;Password=springqa;Trusted_Connection=False"/>
|
|
|
|
|
|
</objects></programlisting>
|
|
|
|
<para>A custom namespace should be registered in the main application
|
|
configuration file to use this syntax. This configuration, only for the
|
|
parsers, is shown below. Additional section handlers are needed to specify
|
|
the rest of the Spring configuration locations as described in previous
|
|
chapters.</para>
|
|
|
|
<programlisting language="myxml"><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" />
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
<parsers>
|
|
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
|
|
</parsers>
|
|
</spring>
|
|
|
|
</configuration></programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Connection String management</title>
|
|
|
|
<para>There are a few options available to help manage your connection
|
|
strings.</para>
|
|
|
|
<para>The first option is to leverage the Spring property replacement
|
|
functionality, as described in <xref
|
|
linkend="objects-factory-placeholderconfigurer" />. This lets you insert
|
|
variable names as placeholders for values in a Spring configuration file.
|
|
In the following example specific parts of a connection string have been
|
|
parameterized but you can also use a variable to set the entire connection
|
|
string.</para>
|
|
|
|
<para>An example of such a setting is shown below</para>
|
|
|
|
<programlisting language="myxml"><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></programlisting>
|
|
|
|
<para>Where <literal>Dao.xml</literal> has a connection string as shown
|
|
below</para>
|
|
|
|
<programlisting language="myxml"><objects xmlns='http://www.springframework.net'
|
|
xmlns:db="http://www.springframework.net/database">
|
|
|
|
<db:provider 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.Core.AdoTemplate, Spring.Data">
|
|
<property name="DbProvider" ref="DbProvider"/>
|
|
</object>
|
|
|
|
<!-- configuration of what values to substitute for ${ } variables listed above -->
|
|
<object name="appConfigPropertyHolder"
|
|
type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
|
|
<property name="configSections" value="DatabaseConfiguration"/>
|
|
</object>
|
|
|
|
</objects></programlisting>
|
|
|
|
<para>Please refer to the Section <xref
|
|
linkend="objects-factory-placeholderconfigurer" /> for more
|
|
information.</para>
|
|
</section>
|
|
|
|
<section xml:id="dbprovider-additional">
|
|
<title>Additional IDbProvider implementations</title>
|
|
|
|
<para>Spring provides some convenient implementations of the IDbProvider
|
|
interface that add addtional behavior on top of the standard
|
|
implementation.</para>
|
|
|
|
<note>
|
|
<para>These provider implementations do not take into account usage with
|
|
NHibernate. NHibernate scopes a SessionFactory, where second level
|
|
caching is managed, to each connection. This <link
|
|
ns6:href="http://forum.springframework.net/showthread.php?t=4462">forum
|
|
thread</link>, contains an implementation of the class
|
|
LocalDelegatingSessionFactoryObject that will create multiple
|
|
SessionFactories for each database connection.</para>
|
|
</note>
|
|
|
|
<section xml:id="dbprovider-usercredentials">
|
|
<title>UserCredentialsDbProvider</title>
|
|
|
|
<para>This <literal>UserCredentialsDbProvider</literal> will allow you
|
|
to change the username and password of a database connection at runtime.
|
|
The API contains the properties <literal>Username</literal> and
|
|
<literal>Password</literal> which are used as the default strings
|
|
representing the user and password in the connection string. You can
|
|
then change the value of these properties in the connection string by
|
|
calling the method <literal>SetCredentialsForCurrentThread</literal> and
|
|
fall back to the default values by calling the method
|
|
<literal>RemoveCredentialsFromCurrentThread</literal>. You call the
|
|
<literal>SetCredentialsForCurrentThread</literal> method at runtime,
|
|
before any data access occurs, to determine which database user should
|
|
be used for the current user-case. Which user to select is up to you.
|
|
You may retrieve the user information from an HTTP session for example.
|
|
Example configuration and usage is shown below</para>
|
|
|
|
<programlisting language="myxml"><object id="DbProvider" type="Spring.Data.Common.UserCredentialsDbProvider, Spring.Data">
|
|
<property name="TargetDbProvider" ref="targetDbProvider"/>
|
|
<property name="Username" value="User ID=defaultName"/>
|
|
<property name="Password" value="Password=defaultPass"/>
|
|
</object>
|
|
|
|
<db:provider id="targetDbProvider" provider="SqlServer-2.0"
|
|
connectionString="Data Source=MARKT60\SQL2005;Database=Spring;Trusted_Connection=False"/></programlisting>
|
|
|
|
<para>If you use dependency injection to configure a class with a
|
|
property of the type <literal>IDbProvider</literal>, you will need to
|
|
downcast to the subtype or you can change your class to have a property
|
|
of the type <literal>UserCredentialsDbProvider</literal> instead of
|
|
<literal>IDbProvider</literal>.</para>
|
|
|
|
<programlisting language="csharp">userCredentialsDbProvider.SetCredentialsForCurrentThread("User ID=springqa", "Password=springqa");</programlisting>
|
|
|
|
<para><literal>UserCredentialsDbProvider's</literal> has a base class,
|
|
<literal>DelegatingDbProvider</literal>, and is intended for you to use
|
|
in your own implementations that delegate calls to a target
|
|
<literal>IDbProvider</literal> instance. This class in meant to be
|
|
subclassed with subclasses overriding only those methods, such as
|
|
<literal>CreateConnection()</literal>, that should not simply delegate
|
|
to the target <literal>IDbProvider</literal>.</para>
|
|
</section>
|
|
|
|
<section xml:id="dbprovider-multidelegating">
|
|
<title>MultiDelegatingDbProvider</title>
|
|
|
|
<para>There are use-cases in which there will need to be a runtime
|
|
selection of the database to connect to among many possible candidates.
|
|
This is often the case where the same schema is installed in separate
|
|
databases for different clients. The
|
|
<literal>MultiDelegatingDbProvider</literal> implements the
|
|
<literal>IDbProvider</literal> interface and provides an abstraction to
|
|
the multiple databases and can be used in DAO layer such that the DAO
|
|
layer is unaware of the switching between databases.
|
|
<literal>MultiDelegatingDbProvider</literal> does its job by looking
|
|
into thread local storage. This storage location stores the name of the
|
|
dbProvider that is to be used for processing the request.
|
|
<literal></literal></para>
|
|
|
|
<para><literal>MultiDelegatingDbProvider</literal> is configured using
|
|
the dictionary property <literal>TargetDbProviders</literal>. The key of
|
|
this dictionary contains the name of a dbProvider and its value is a
|
|
dbProvider object. You can also provide this dictionary as a constructor
|
|
argument. The property <property>DefaultDbProvider</property> can be set
|
|
with the name of the DbProvider to use if no provider name is found in
|
|
thread local storage</para>
|
|
|
|
<para>During request processing, once you have determined which target
|
|
dbProvider should be use, in this example database1ProviderName, you
|
|
should execute the following code is you are using Spring 1.2 M1 or
|
|
later</para>
|
|
|
|
<programlisting language="csharp">// Spring 1.3.0 or later
|
|
MultiDelegatingDbProvider.CurrentDbProviderName = "database1ProviderName"
|
|
|
|
// Spring 1.2 M1 or later
|
|
<classname>LogicalThreadContext</classname>.SetData(<classname>MultiDelegatingDbProvider</classname>.CURRENT_DBPROVIDER_SLOTNAME, "database1ProviderName")
|
|
</programlisting>
|
|
|
|
<para>and the following ocde if you are using earlier versions</para>
|
|
|
|
<programlisting language="csharp">// Prior to Spring 1.2 M1
|
|
<classname>LogicalThreadContext</classname>.SetData("dbProviderName", "database1ProviderName")</programlisting>
|
|
|
|
<para>and then call the data access layer.</para>
|
|
|
|
<note>
|
|
<para>If you do not change the name of the IDbProvider stored in
|
|
thread local storage during request processing, say in the web tier
|
|
where a user is identified, then you will always refer to the default
|
|
provider if the property <property>DefaultDbProvider</property> has
|
|
been set. If the <property>DefaultDbProvider</property> property has
|
|
not been set than an InvalidDataAccessApiUsageException will be
|
|
thrown.</para>
|
|
</note>
|
|
|
|
<para>Here is a sample configuration to build up an object definition
|
|
for <literal>MultiDelegatingDbProvider</literal>.</para>
|
|
|
|
<programlisting language="myxml"><db:provider id="CreditAndDebitsDbProvider"
|
|
provider="System.Data.SqlClient"
|
|
connectionString="Data Source=MARKT60\SQL2005;Initial Catalog=CreditsAndDebits;User ID=springqa; Password=springqa"/>
|
|
|
|
<db:provider id="CreditDbProvider"
|
|
provider="System.Data.SqlClient"
|
|
connectionString="Data Source=MARKT60\SQL2005;Initial Catalog=Credits;User ID=springqa; Password=springqa"/>
|
|
|
|
<object id="dbProviderDictionary" type="Spring.Collections.SynchronizedHashtable, Spring.Core">
|
|
<property name="['DbProvider1']" ref="CreditAndDebitsDbProvider"/>
|
|
<property name="['DbProvider2']" ref="CreditDbProvider"/>
|
|
</object>
|
|
|
|
<object id="DbProvider" type="Spring.Data.MultiDelegatingDbProvider, Spring.Data">
|
|
<property name="TargetDbProviders" ref="dbProviderDictionary"/>
|
|
<property name="DefaultDbProvider" value="CreditDbProvider"/>
|
|
</object></programlisting>
|
|
|
|
<para>As seen above, MultidelegatingDbProvider works via a thread local
|
|
storage mechansims. If you prefer to place the logic to switch databases
|
|
in a single location, within a single class, then create a subclass
|
|
MultiDelegatingDbProvider and override the method GetTargetProvider. You
|
|
can then select which provider to return based on your own
|
|
implementation that does not involve thread local storage.</para>
|
|
|
|
<note>
|
|
<para>This class is not recommended for usage with NHibernate.
|
|
NHibernate usage typically involves caches that are scoped at the
|
|
level of the SessionFactory. If you switch the database that hibernate
|
|
is pointing to and do not also managed switching the cache, then the
|
|
cache will end up with results from two different databases - which of
|
|
course you don't want to have. The helper class contained in this
|
|
<link
|
|
ns6:href="http://forum.springframework.net/showthread.php?p=11234#post11234">post</link>
|
|
may help you if you when using NHibernate with multiple
|
|
databases.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
</chapter>
|