• ADO.NET数据提供程序


    ADO.NET数据提供程序

    简介

             本文从构建一个简单的工厂模式创建适合的数据提供程序(DataProvider)开始,到使用 ADO.NET 为我们提供的DbProviderFactories 来创建一个适合的数据提供程序结束。并补充了去除简化工厂模式中的 case 语句,使用反射的方式简化工厂模式。

    自定义工厂模型

             首先,假设我们要提供访问以下数据库,如:Sqlserver、MySQL、Oracle、OleDb、… 。

    接着,我们可以定义一个方法根据传入参数的不同,创建不同的连接对象。

    private static IDbConnection GetConnection(string provider)
    {
        IDbConnection conn = null;
        switch (provider)
        {
            case "SqlServer":
                conn = new SqlConnection();
                break;
            case "MySQL":
                // 需要添加程序集:mysql.data.dll
                // 并引用命名空间 MySql.Data.MySqlClient
                conn = new MySqlConnection();
                break;
            case "Oracle": 
                // 需要引用程序集:System.Data.OracleClient.dll
                // 并引用命名空间 System.Data.OracleClient
                conn = new OracleConnection();
                break;
            case "OleDb":
                conn = new OleDbConnection();
                break;
        }
        return conn;
    }

    既然 case 中固定的这几个连接对象,何不改为枚举值呢?

    下面定义了一个枚举类型:

    /// <summary>
    /// 数据提供程序枚举
    /// </summary>
    enum DataProviderEnum
    {
        SqlServer, MySQL, Oracle, OleDb, None
    }

    接着,更改上面的GetConnection():

    /// <summary>
    /// 根据传入枚举值,创建对应的数据库连接对象
    /// </summary>
    private static IDbConnection GetConnection(DataProviderEnum provider)
    {
        IDbConnection conn;
        switch (provider)
        {
            case DataProviderEnum.SqlServer:
                conn = new SqlConnection();
                break;
            case DataProviderEnum.MySQL:
                // 需要添加程序集:mysql.data.dll
                // 并引用命名空间 MySql.Data.MySqlClient
                conn = new MySqlConnection();
                break;
            case DataProviderEnum.Oracle:
                // 需要引用程序集:System.Data.OracleClient.dll
                // 并引用命名空间 System.Data.OracleClient
                conn = new OracleConnection();
                break;
            case DataProviderEnum.OleDb:
                conn = new OleDbConnection();
                break;
        }
        return conn;
    }


    下面来验证一下,我们上面的代码是否能够正确执行:

    static void Main()
    {
        Console.WriteLine("Simple Connection Factory.
    ");
    
        IDbConnection conn = GetConnection(DataProviderEnum.MySQL);
        if (conn == null)
        {
            throw new NullReferenceException("conn is not allow null!");
        }
        Console.WriteLine(conn.GetType().FullName);
    
        Console.Read();
    }

    执行结果如下图:

               

    可见,我们的程序能够正确执行。

    Note: MySQL 程序集下载地址: http://dev.mysql.com/downloads/connector/net/5.2.html

    ADO.NET 数据提供程序工厂模型

             Microsoft 为我们提供了一个 DbProviderFactories 类,该类有一个静态方法 GetFactory(), 能够获得指定的数据提供程序的 DbProviderFactory。

    Note: DbProviderFactories 类型只能从获取有效的数据提供程序列表中获取相应的 DbProviderFactory。有效的数据提供程序列表记录在machine.config 文件的 <DbProviderFactory> 节点内。(C:WindowsMicrosoft.NETFrameworkv2.0.50727CONFIGmachine.config)

    <system.data>
        <DbProviderFactories>
           <add name="Odbc Data Provider" invariant="System.Data.Odbc" description=".Net Fram
           <add name="OleDb Data Provider" invariant="System.Data.OleDb" description=".Net Fr
           <add name="OracleClient Data Provider" invariant="System.Data.OracleClient" descri
           <add name="SqlClient Data Provider" invariant="System.Data.SqlClient" description=
        </DbProviderFactories>
    </system.data>

    上面代码中的 invariant 的值既是 GetFactory() 所需的参数。

    这里,没有 MySQL 的数据提供程序,我们可以增加新的不变值指向GAC(全局程序集缓存),路径:C:Windowsassembly。关于这个话题,可以参考程序集相关章节,这里不做介绍。

    你也可以通过代码来查看所支持的提供程序列表:

    // 获取支持的数据提供程序
    public void PrintProviderTalbe()
    {
        DataTable table = DbProviderFactories.GetFactoryClasses();
        for (int i = 0; i < table.Rows.Count; i++)
        {
            Console.WriteLine("{0}", table.Rows[i][0]);
        }
    }

    使用 DbProviderFactories 创建提供程序

    public static void ExecuteNonQuery(string cmdText)
    {
        string providerName = "System.Data.SqlClient";
        string connStr = "Data Source=.; Integrated Security=SSPI; Initial Catalog=DataBaseName";
    
        // 获取提供程序
        DbProviderFactory provider = DbProviderFactories.GetFactory(providerName);
    
        // 创建连接对象
        DbConnection connection = provider.CreateConnection();
        connection.ConnectionString = connStr;
        connection.Open();
    
        // 创建命令对象
        DbCommand command = provider.CreateCommand();
        command.CommandText = cmdText;
        command.Connection = connection;
        command.ExecuteNonQuery();
    }


    上面的方法实现了完整的获取提供程序对象,创建连接对象和命令对象的方式。通常情况下,我们会把 providerName 和 connStr 放到配置文件中,从配置文件中获取,这样就不用每次重新编译程序集。

    下面我们来改下这个方法:

    string providerName = ConfigurationManager.AppSettings["SqlProvider"];
    string connStr = ConfigurationManager.ConnectionStrings["SqlConnStr"];

    Note:使用 ConfigurationManager 需要引用 System.Configuration.dll

    Config 文件如下:

    <appSettings>
      <add key="SqlProvider" value="System.Data.SqlClient"/>
      <add key="OleDbProvider" value="System.Data.OleDb"/>
    </appSettings>
    
    <!--Here are the connection strings-->
    <connectionStrings>
      <add name="SqlConnStr" connectionString="Data Source=.; Initial Catalog=DataBaseName; Integrated Security=SSPI"/>
      <add name="OleDbConnStr" connectionString="Provider=SQLOLEDB; Data Source=.; Initial Catalog=DataBaseName; Integrated Security=SSPI"/>
    </connectionStrings>

    注意:<appSettings> 与 <connectionStrings> 这两个的不同之处,可以这么理解,<connectionStrings> 是专门用来提供配置连接字符串的,而 <appSettings> 以键值对的方式为应用程序提供额外的配置。

    补充:

    使用反射的方式简化简单工厂中的 Switch(),将代码改为如下:

    /// <summary>
    /// 使用反射获取数据库连接对象
    /// </summary>
    /// <param name="assemblyName">程序集名称</param>
    /// <param name="providerFullName">类型完整名称</param>
    /// <returns>合适的数据库连接对象</returns>
    private static IDbConnection GetConnection(string assemblyName, string providerFullName)
    {
        IDbConnection conn = null;
        conn = (IDbConnection)Assembly.Load(assemblyName).CreateInstance(providerFullName);
        return conn;
    }

    Main() 方法中代码如下:

    IDbConnection conn = GetConnection("mysql.data", "MySql.Data.MySqlClient.MySqlConnection");
    Console.WriteLine(conn.GetType().FullName);

    结束语

             虽然提供程序的工厂模式能让我们访问不同的数据库,但是这种模式,同样也限制了我们对特定数据库访问的灵活性,因为该模式站在一个更好的抽象层次上,着重点在通用,适合所有的数据提供对象,虽然,可以使用类型转换,但是因此会增加许多运行时的检测来保证转换不会抛出异常。本文只是一个基础的使用介绍,在此基础上,你可以构建一个完整的通用数据访问层。

  • 相关阅读:
    UE4——查找指定类型或名称的Actor对象
    unity 替换渲染 ( Rendering with Replaced Shaders )
    浅谈Java消息服务(JMS)规范与ActiveMQ实现
    初识WebSocket(一)--WebSocket介绍与实现简单web群聊
    IDEA编译器常用快捷键总结
    初识Docker(二)--Docker常用命令
    初识Docker(一)--Docker介绍及安装
    自定义hexo博客melody主题标签页title
    vue+springboot+el-uolpad组件实现文件上传
    判断一个数是否为2的整数次幂
  • 原文地址:https://www.cnblogs.com/kanlei/p/3427845.html
Copyright © 2020-2023  润新知