ADO.NET數據提供程序

ADO.NET數據提供程序

簡介

         本文從構建一個簡單的工廠模式建立適合的數據提供程序(DataProvider)開始,到使用 ADO.NET 爲咱們提供的DbProviderFactories 來建立一個適合的數據提供程序結束。並補充了去除簡化工廠模式中的 case 語句,使用反射的方式簡化工廠模式。html

自定義工廠模型

         首先,假設咱們要提供訪問如下數據庫,如:Sqlserver、MySQL、Oracle、OleDb、… 。mysql

接着,咱們能夠定義一個方法根據傳入參數的不一樣,建立不一樣的鏈接對象。sql

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():app

/// <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;
}


下面來驗證一下,咱們上面的代碼是否可以正確執行:ide

static void Main()
{
    Console.WriteLine("Simple Connection Factory.\n");

    IDbConnection conn = GetConnection(DataProviderEnum.MySQL);
    if (conn == null)
    {
        throw new NullReferenceException("conn is not allow null!");
    }
    Console.WriteLine(conn.GetType().FullName);

    Console.Read();
}

執行結果以下圖:spa

           

可見,咱們的程序可以正確執行。code

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

 

ADO.NET 數據提供程序工廠模型

         Microsoft 爲咱們提供了一個 DbProviderFactories 類,該類有一個靜態方法 GetFactory(), 可以得到指定的數據提供程序的 DbProviderFactory。

Note: DbProviderFactories 類型只能從獲取有效的數據提供程序列表中獲取相應的 DbProviderFactory。有效的數據提供程序列表記錄在machine.config 文件的 <DbProviderFactory> 節點內。(C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.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:\Windows\assembly\。關於這個話題,能夠參考程序集相關章節,這裏不作介紹。

你也能夠經過代碼來查看所支持的提供程序列表:

// 獲取支持的數據提供程序
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);

 

結束語

         雖然提供程序的工廠模式能讓咱們訪問不一樣的數據庫,可是這種模式,一樣也限制了咱們對特定數據庫訪問的靈活性,由於該模式站在一個更好的抽象層次上,着重點在通用,適合全部的數據提供對象,雖然,可使用類型轉換,可是所以會增長許多運行時的檢測來保證轉換不會拋出異常。本文只是一個基礎的使用介紹,在此基礎上,你能夠構建一個完整的通用數據訪問層。

相關文章
相關標籤/搜索