2013年4月15日星期一

企业库中 DatabaseFactory.CreateDatabase 方法创建数据库实例的 逻辑过程(转)

 Enterprise Library 的 数据访问应用块中:
  Microsoft.Practices.EnterpriseLibrary.Data.Database 抽象类派生出了以下三个数据库类
     Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase
     Microsoft.Practices.EnterpriseLibrary.Data.Oracle.OracleDatabase
     Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase
从这一点知识我们就可以知道
Database dbSvc = DatabaseFactory.CreateDatabase();
上述代码创建的 dbSvc 并不是 Microsoft.Practices.EnterpriseLibrary.Data.Database 抽象类的实例,而应该是下面这三个类的其中一个实例。
     Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase
     Microsoft.Practices.EnterpriseLibrary.Data.Oracle.OracleDatabase
     Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase
 或者是你自己新写的一个派生自 Database 抽象类的子类。
我们再通过查看企业库的源代码简单看一下  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 抽象类的那一个实例用的。
参考资料:

没有评论:

发表评论