本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《
在配置文件里除了 常见的system.net、system.data等节点之外, 还可以自已写 XML 格式的配置元素,这些元素叫做节(Section)。当然,如果你自己写一堆复杂的 XML 格式的标签,.NET 自身是不知道如何解析的,因此这里就需要你在指定节的同时,告诉 .NET 如何处理它们,也就是定义“节处理器”(Section Handlers)。
<
add
databaseType
="
Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
"
name
="
Data.Usp.mssql
" />
</
providerMappings
>
</
dataConfiguration
>
它包含了两个东西:
属性:
defaultDatabase
和节点:
providerMappings
,如果DAAB写程序读取配置,需要处理这两个东西。
接下来我们打开Enterprise library 2006.Jan的Data solution,看看Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings是怎么定义的。
/// <remarks>
/// <para>The class maps to the <c>databaseSettings</c> element in configuration.</para>
/// </remarks>
public class DatabaseSettings :
SerializableConfigurationSection
Enterprise Library 的配置框架建立在 System.Configuration 的基础之上,而且工作方式也与其非常相似。应用程序块的配置节派生自 Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SerializableConfigurationSection,而不是直接从 System.Configuration.ConfigurationSection 派生。
SerializableConfigurationSection 也是Microsoft.Practices.EnterpriseLibrary.Common.Configuration下的类,是从ConfigurationSection, IXmlSerializable类继承可以看出是对ConfigurationSection的扩展,而每个EntLib应用程序块的配置节点都必须继承自此类,此类主要包括了对XML文件节点的操作方法。
{
private const string defaultDatabaseProperty = "defaultDatabase";
private const string dbProviderMappingsProperty = "providerMappings";
/// <summary>
/// The name of the data configuration section.
/// </summary>
public const string SectionName = "dataConfiguration";
最重要的代码是:
public static DatabaseSettings GetDatabaseSettings(IConfigurationSource configurationSource)
{
return (DatabaseSettings)configurationSource.GetSection(SectionName);
}
它的意义就是,从配置文件中指定dataConfiguration名的节点树把配置读取到ConfigurationSection对象中。
之后就可以:
对于属性,它这么处理:
[ConfigurationProperty(defaultDatabaseProperty, IsRequired = false)]
public string DefaultDatabase
{
get
{
return (string)this[defaultDatabaseProperty];
}
set
{
this[defaultDatabaseProperty] = value;
}
}
对于节点,它这么处理:
[ConfigurationProperty(dbProviderMappingsProperty, IsRequired = false)]
public NamedElementCollection<DbProviderMapping> ProviderMappings
{
get
{
return (NamedElementCollection<DbProviderMapping>)base[dbProviderMappingsProperty];
}
}
示意如下:
配置节点详解
我们在配置文件中用
<system.data>
<DbProviderFactories>
<add
name="Sql Server 2005"
invariant="
Data.Usp.mssql
"
description="An alias for the SqlProvider"
type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</DbProviderFactories>
</system.data>
设定了database的provider,在这里可以指定很多种不同的provider,比如:
<system.data>
<DbProviderFactories>
<add name="my Generic Database" invariant="
MyOleDBDatabase
" description="An alias for the OleDBProvider" type="System.Data.OleDb.OleDbFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</DbProviderFactories>
</system.data>
此时要用自己定义的provider,就可以这么定义连接字符串:
<connectionStrings>
<add name="MyTestConnectionString" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\My2005Codes\TestCode\AccessDB.mdb;"
providerName="
MyOleDBDatabase
" />
</connectionStrings>
当然,也可以不用在这里指定,而是后面连接字符串配置节点中直接指定已有的provider。
我们现在的连接字符串配置是:
<connectionStrings>
<add
name="Authentication"
providerName="
System.Data.SqlClient
"
connectionString="Server=11.168.1.22;database=DB_Authentication;UID=usp;PWD=de;" />
<add
name="Log"
providerName="
Data.Usp.mssql
"
connectionString="Server=11.168.1.22;DataBase=DB_Log;UID=logger;PWD=de;" />
</connectionStrings>
那么,实际上这个“
System.Data.SqlClient
”就是系统约定的provider名,用我们自定义的“
Data.Usp.mssql
”也可以达到同样的效果。
当我们调用
DatabaseFactory.CreateDatabase("Authentication");
时,实际上就是命令DAAB用
<add
name="Authentication"
providerName="
System.Data.SqlClient
"
connectionString="Server=11.168.1.22;database=DB_Authentication;UID=usp;PWD=de;" />
所指定的连接字符串去连数据库。
辅助参考蝈蝈俊的blog:
DatabaseFactory.CreateDatabase 方法创建数据库实例的 逻辑过程
简单看一下 DatabaseFactory.CreateDatabase 方法 是根据啥关系,来判断应该创建的是 Database 抽象类的那个子类。
分析代码可知,这里的判断分三步:
主要代码看 DatabaseCustomFactory.cs 文件的
public object CreateObject(IBuilderContext context, string name, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache)方法。
第一步:
在链接字符串中,我们可以根据链接字符串的 name 获得 链接字符串的 providerName 。
第二步:
如果 我们设置了 providerName 的任何 影射关系, 则自动获得 这个映射的 DbProviderMapping ;
如果这个数据库访问者 没有被设置任何影射关系, 则 系统自动在默认提供的 SqlDatabase、 OracleDatabase 中匹配。
如果上述都没匹配出结果, 则 返回 GenericDatabase 。
上述逻辑在 DatabaseConfigurationView.cs 文件中可以看到代码:
public DbProviderMapping GetProviderMapping(string name, string dbProviderName)
{
DatabaseSettings settings = this.DatabaseSettings;
if (settings != null)
{
DbProviderMapping existingMapping = settings.ProviderMappings.Get(dbProviderName);
if (existingMapping != null)
{
return existingMapping;
}
}
DbProviderMapping defaultMapping = this.GetDefaultMapping(name, dbProviderName);
if (defaultMapping != null)
{
return defaultMapping;
}
return this.GetGenericMapping();
}
第三步
根据 DbProviderMapping 生成 Database 抽象类的实例。
根据上述逻辑描述,我们就可以理解如下一个数据库的配置文件了。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<dataConfiguration defaultDatabase="MyTestConnectionString">
<providerMappings>
<add databaseType="Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
name="GenericDatabase" />
<add databaseType="Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
name="System.Data.SqlClient" />
</providerMappings>
</dataConfiguration>
<connectionStrings>
<add name="MyTestConnectionString" connectionString="server=(local)\SQLEXPRESS;database=EntLibQuickStarts;Integrated Security=true;"
providerName="GenericDatabase" />
</connectionStrings>
<system.data>
<DbProviderFactories>
<add name="my Generic Database" invariant="GenericDatabase" description="An alias for the SqlProvider" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</DbProviderFactories>
</system.data>
</configuration>
这个数据库配置文件生成的 Database dbSvc = DatabaseFactory.CreateDatabase();
dbSvc 必然是 Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase 类型的。
注意:
system.data 数据节 的 DbProviderFactories 配置节 是给配置文件中 connectionStrings 节的 providerName 对应用的。
而 dataConfiguration 配置节的 providerMappings 是给 生成 的 是那一个 Database 抽象类的那一个实例用的。
参考资料: