天天看點

使用反射+抽象工廠的資料通路(1)

應用程式有時需要适應于不同的資料庫,例如要将一個Access資料庫的網站改成使用Sql Server資料庫。由于SQL Server和Access在ADO.Net上的使用是不同的,SQL Server使用的是System.Data.SqlClient命名空間下的SqlConnection、SqlCommand、SqlParameter、SqlDataReader、SqlDataAdapter,而Access則使用的是System.Data.Oledb命名空間下的相應的類。是以需要大量的查找、替換工作,這不是一個聰明的方式。如何使用軟體設計模式,以不變應萬變,保證代碼的修改量是最小的呢?最基本的思想就是:将相同部分的代碼提取出來,做成單獨的類或接口,通過增加層次來提高代碼的重用性。

例如,對于Access和SQL Server,都需要使用一段類似的代碼來建立資料庫的連接配接。

Access的格式

using System;

using System.Data;

using <b>System.Data.Oledb</b>;

private <b>OledbConnection</b> conn;

private void OpenConnection()

{

       string strConnection;

conn=new <b>System.Data.Oledb.OledbConnection</b>(strConnection)

}

Sql Server 的格式

注意:除了上面黑體部分不同之外,其他代碼都一模一樣。如果能将這些黑體文字替換成一種對于Access、Sql Server都通用的Connection對象,具體使用什麼資料庫,系統隻需要作一個簡單設定,如通過Web.Config設定或定義一個字元串指定資料庫的類型,那多友善啊。

<b>抽象工廠模式(Abstract Factory Pattern</b><b>)簡介</b>

抽象工廠模式有下面的一些優點和缺點:

1) 它分離了具體的類。Abstract Factory模式幫助你控制一個應用建立的對象的類。因為一個工廠封裝建立産品對象的責任和過程,它将客戶與類的實作分離。客戶通過它們的抽象接口操縱執行個體。産品的類名也在具體工廠的實作中被分離;它們不出現在客戶代碼中。

2) 它使得易于交換産品系列一個具體工廠類在一個應用中僅出現一次—即在它初始化的時候。這使得改變一個應用的具體工廠變得很容易。它隻需改變具體的工廠即可使用不同的産品配置,這是因為一個抽象工廠建立了一個完整的産品系列,是以整個産品系列會立刻改變。在我們的使用者界面的例子中,我們僅需轉換到相應的工廠對象并重新建立接口,就可實作從M o t i f視窗元件轉換為Presentation Manager視窗元件。

3) 它有利于産品的一緻性當一個系列中的産品對象被設計成一起工作時,一個應用一次隻能使用同一個系列中的對象,這一點很重要。而A b s t r a c t F a c t o r y很容易實作這一點。

4) 難以支援新種類的産品難以擴充抽象工廠以生産新種類的産品。這是因為A b s t r a c t F a c t o r y接口确定了可以被建立的産品集合。支援新種類的産品就需要擴充該工廠接口,這将涉及A b s t r a c t F a c t o r y類及其所有子類的改變。

<b>具體代碼實作</b>

<b>1</b><b>、定義抽象工廠類(DbProviderFactories.cs</b><b>)。</b>

抽象工廠類需要傳回多個具體類(多種資料庫)中的一個。是以GetFactory()傳回的類型是一個具體的工廠類<b>。</b>

using System.Web;

using System.Configuration;

using System.Data.Common;

using Microsoft.Win32;

namespace SplendidCRM

       /// &lt;summary&gt;

       /// Summary description for DbProviderFactories.

       /// &lt;/summary&gt;

       public class DbProviderFactories

       {

              public static <b>DbProviderFactory</b> GetFactory()

              {

                     // 從Application中擷取資訊

HttpApplicationState Application = HttpContext.Current.Application;

                     string sSplendidProvider = Sql.ToString(Application["SplendidProvider"]);

                     string sConnectionString = Sql.ToString(Application["ConnectionString"]);

                     // 如果在Application沒有資訊,則從Web.Config中擷取。

/*

&lt;configuration&gt;

  &lt;appSettings&gt;

    &lt;add key="SplendidProvider" value="System.Data.SqlClient" /&gt;

    &lt;add key="SplendidSQLServer" value="Password=123;User ID=sa;Initial Catalog=DB;Data Source=WWW;Packet Size=4096" /&gt;

  &lt;/appSettings&gt;

*/

                     if ( Sql.IsEmptyString(sSplendidProvider) || Sql.IsEmptyString(sConnectionString) )

                     {

                            sSplendidProvider = ConfigurationSettings.AppSettings["SplendidProvider"];

                            switch ( sSplendidProvider )

                            {

                                   case "System.Data.SqlClient":

                                          sConnectionString = ConfigurationSettings.AppSettings["SplendidSQLServer"];

                                          break;

                                   case "System.Data.OracleClient":

                                          sConnectionString = ConfigurationSettings.AppSettings["SplendidSystemOracle"];

                                   case "Oracle.DataAccess.Client":

                                          sConnectionString = ConfigurationSettings.AppSettings["SplendidOracle"];

                            }

                            Application["SplendidProvider"] = sSplendidProvider;

                            Application["ConnectionString"] = sConnectionString;

                     }

                     return GetFactory(sSplendidProvider, sConnectionString);

              }

              ///

              public static <b>DbProviderFactory</b> GetFactory(string sSplendidProvider, string sConnectionString)

                     switch ( sSplendidProvider )

                            case "System.Data.SqlClient":

                                   return new SqlClientFactory(sConnectionString);

                            case "System.Data.OracleClient":

                                   return new OracleSystemDataFactory(sConnectionString);

                            case "Oracle.DataAccess.Client":

                                   return new OracleClientFactory(sConnectionString);

                            default:

                                   throw(new Exception("不支援的factory " + sSplendidProvider));

       }

<b></b>

<b>   本文轉自My_King1 51CTO部落格,原文連結:http://blog.51cto.com/apprentice/1360592</b><b>,如需轉載請自行聯系原作者</b>