前不久想使用下EF的通用单表增删改的特性,当时使用控制台做测试,怎么弄都没成功,原因出在app.config中,反而在mvc项目中,就没有任何问题。在反复的更改配置的过程中,发现了DbProviderFactory这个类,好奇打开看看其定义。
// 摘要: // 表示一组方法,这些方法用于创建提供程序对数据源类的实现的实例。 public abstract class DbProviderFactory { // 摘要: // 初始化 System.Data.Common.DbProviderFactory 类的新实例。 protected DbProviderFactory(); // 摘要: // 指定特定的 System.Data.Common.DbProviderFactory 是否支持 System.Data.Common.DbDataSourceEnumerator // 类。 // // 返回结果: // 如果 System.Data.Common.DbProviderFactory 的实例支持 System.Data.Common.DbDataSourceEnumerator // 类,则为 true;否则为 false。 public virtual bool CanCreateDataSourceEnumerator { get; } // 摘要: // 返回实现 System.Data.Common.DbCommand 类的提供程序的类的一个新实例。 // // 返回结果: // System.Data.Common.DbCommand 的新实例。 public virtual DbCommand CreateCommand(); // // 摘要: // 返回实现 System.Data.Common.DbCommandBuilder 类的提供程序的类的一个新实例。 // // 返回结果: // System.Data.Common.DbCommandBuilder 的新实例。 public virtual DbCommandBuilder CreateCommandBuilder(); // // 摘要: // 返回实现 System.Data.Common.DbConnection 类的提供程序的类的一个新实例。 // // 返回结果: // System.Data.Common.DbConnection 的新实例。 public virtual DbConnection CreateConnection(); // // 摘要: // 返回实现 System.Data.Common.DbConnectionStringBuilder 类的提供程序的类的一个新实例。 // // 返回结果: // System.Data.Common.DbConnectionStringBuilder 的新实例。 public virtual DbConnectionStringBuilder CreateConnectionStringBuilder(); // // 摘要: // 返回实现 System.Data.Common.DbDataAdapter 类的提供程序的类的一个新实例。 // // 返回结果: // System.Data.Common.DbDataAdapter 的新实例。 public virtual DbDataAdapter CreateDataAdapter(); // // 摘要: // 返回实现 System.Data.Common.DbDataSourceEnumerator 类的提供程序的类的一个新实例。 // // 返回结果: // System.Data.Common.DbDataSourceEnumerator 的新实例。 public virtual DbDataSourceEnumerator CreateDataSourceEnumerator(); // // 摘要: // 返回实现 System.Data.Common.DbParameter 类的提供程序的类的一个新实例。 // // 返回结果: // System.Data.Common.DbParameter 的新实例。 public virtual DbParameter CreateParameter(); // // 摘要: // 返回提供程序的类的新实例,该实例可实现提供程序的 System.Security.CodeAccessPermission 类的版本。 // // 参数: // state: // System.Security.Permissions.PermissionState 值之一。 // // 返回结果: // 指定 System.Security.Permissions.PermissionState 的 System.Security.CodeAccessPermission // 对象。 public virtual CodeAccessPermission CreatePermission(PermissionState state); }
数据库5大对象全了。我想是不是可以通过它来构建出更抽象的数据库访问。后来查询相关资料,并阅读了 PetaPoco 这个微型Orm的源代码,发现其也是使用DbProviderFactory 来创建数据库连接等对象的。
反观自己在最初学习SQLServer,Oracle,Sqlite时,分别封装了SqlHelp,OracleHelp,SqliteHelp等简化数据库的操作,当时还洋洋自得,现在看来很是无语,代码几乎是一致的,无非是使用的Connection、Command、Adapter、Parameter 等对象的不同,如果使用DbProviderFactory来隔绝具体的实例,是不是可以把这3个数据库Help类封装成一个通用的DbHelp呢?
DbProviderFactory 导入外部的Provider
初步测试是可以的,不过在通过config文件载入DbProviderFactory时遇到点问题,花费了好一会。过程就不说了,如使用Oracle官网的dll,正确的配置是这样:
<system.data>
<DbProviderFactories>
<add name="OracleClientFactory" invariant="OracleClientFactory" description="Oracle.ManagedDataAccess.Client.OracleClientFactory" type="Oracle.ManagedDataAccess.Client.OracleClientFactory,Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</DbProviderFactories>
</system.data>
其中要注意的,是 invariant 和 type 属性。
invariant: 可以通过这个属性值获取到对应DbProviderFactory类型。如,DbProviderFactories.GetFactory("OracleClientFactory") ;
type:类名(含命名空间),程序集名称,程序集信息。
我们经常可以在web.config文件中看到类似的type信息,但如果是自己拓展,或者刚刚从Oracle官网上下载的组件呢,该如何得到这些信息。使用Reflector就可以轻松看到,以前一直用Reflector,但从没关注过这一块。
另外通过 DbProviderFactories.GetFactoryClasses(); 可以查看到所有被安装的Provider 哦,通过配置文件导入的也会在其中显示。
<system.data> <DbProviderFactories> <add name="SQLiteFactory" invariant="SQLiteFactory" description="xxxxxxx" type="System.Data.SQLite.SQLiteFactory,System.Data.SQLite" /> </DbProviderFactories> </system.data> 检测配置是否成功 var sqlite = DbProviderFactories.GetFactory("SQLiteFactory");