工廠模式連接數據庫


在項目中通常可能會使用不同的數據源,可能是SQL Server也可能是ACCESS或者是Oracle,那么如何保證在使用不同數據源的時候,使項目代碼更改的代價最小呢?
對,使用工廠模式.在Net1.1的時候,這需要項目實施者自己來完成.在Net2.0中,MS已經新增了幾個用於實施工廠模式的類庫.
首先我現在應用程序當前目錄下新建Databases目錄,再新建一個Access數據庫與Sqlserver數據庫
其中這2個數據庫的結構都是一樣的,都包含一個SampleData表,有ID,與IntegerValue字段

然后回到VS中新建一個WinForm 項目,然后編輯App.Config文件如下:

 

xml version="1.0" encoding="utf-8" ?>

   這里記錄着實施項目中可能會用到的數據庫連接信息
   providerName 記錄數據驅動
   connectionString 數據源連接字符串 |DataDirectory|指應用程序當前目錄
-->

   
   
 
          這里使用SqlServer2005直接在應用程序中附加數據庫
      
 -->
       
          connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Databases\MyData.mdf;Integrated Security=True;User Instance=True" />
       
          connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\Databases\MyData.mdb;Persist Security Info=True" />   
    connectionStrings>

configuration>

 

然后在主窗體中的Button事件中編寫如下代碼

private void getDataButton_Click(object sender, EventArgs e)
        {
            try
            {
                //創建一個新的StopWatch來監視連接性能[Net2.0新增]
                Stopwatch myWatch = new Stopwatch();

                // 開始計算connection and retrieval of data所花費的時間
                myWatch.Start();

                // 選擇要使用的數據源
                string strDataSource="MS Access";

                // 根據選者的數據源獲得連接字符串的配置對象               
                ConnectionStringSettings objConnectionSettings = ConfigurationManager.ConnectionStrings[strDataSource];

                // 通過配置文件創建數據庫驅動工廠的實例
                DbProviderFactory objProviderFactory = DbProviderFactories.GetFactory(objConnectionSettings.ProviderName);

                // 通過數據庫驅動工廠創建DBConnection實例
                using (DbConnection objConnection = objProviderFactory.CreateConnection())
                {
               
                // 從 objConnectionSettings 中獲取連接字符串
                objConnection.ConnectionString = objConnectionSettings.ConnectionString;

                // 打開 connection
                objConnection.Open();

                // 通過數據驅動工廠創建 數據適配器和 Command
                DbDataAdapter myAdapter = objProviderFactory.CreateDataAdapter();
                DbCommand myCommand = objProviderFactory.CreateCommand();
               
           
                string myQuery = "SELECT * FROM SampleData";
                DataSet myDataSet = new DataSet();

                myCommand.Connection = objConnection;
                myCommand.CommandText = myQuery;

                myAdapter.SelectCommand = myCommand;

                myAdapter.Fill(myDataSet);
               
                displayDataGridView.DataSource = myDataSet.Tables[0];

                // 停止StopWatch來查看連接和返回數據所花費的時間
                myWatch.Stop();
                elapsedTimeTextLabel.Text = "消耗時間: "   myWatch.ElapsedMilliseconds.ToString() " ms";
                providerLabel.Text = "數據驅動: " objConnectionSettings.ProviderName.ToString();
                connectionStringLabel.Text = objConnectionSettings.ConnectionString.ToString();
            }
            }
            catch
            {
                MessageBox.Show("出現錯誤.", "Alert");
            }
           
        }
    }

 

這樣,只需要更改strDataSource就可以使用不同的數據源,而且整個項目都不需要為不同的數據庫而煩惱
=====================================================================================================

使用設計模式構建通用數據庫訪問類

在應用程序的設計中,數據庫的訪問是非常重要的,我們通常需要將對數據庫的訪問集中起來,以保證良好的封裝性和可維護性。在.Net中,數據庫的訪問,對於微軟自家的SqlServer和其他數據庫(支持OleDb),采用不同的訪問方法,這些類分別分布於System.Data.SqlClient和System.Data.OleDb名稱空間中。微軟后來又推出了專門用於訪問Oracle數據庫的類庫。我們希望在編寫應用系統的時候,不因這么多類的不同而受到影響,能夠盡量做到數據庫無關,當后台數據庫發生變更的時候,不需要更改客戶端的代碼。

這就需要我們在實際開發過程中將這些數據庫訪問類再作一次封裝。經過這樣的封裝,不僅可以達到上述的目標,還可以減少操作數據庫的步驟,減少代碼編寫量。在這個方面,微軟為我們提供了Application Block,但是,可惜的是目前只支持Sql Server。這里,介紹一種在實際應用中得到了非常好的效果的實作策略——筆者編寫的Websharp框架中的數據訪問結構。Factory設計模式是使用的主要方法。

我們先來看看Factory的含義:定義一個用於創建對象的接口,讓子類決定實例化哪一個類。Factory Method使一個類的實例化延遲到其子類。我們這里可能會處理對多種數據庫的操作,因此,需要首先定義一個操縱數據庫的接口,然后,根據數據庫的不同,由類工廠決定實例化哪個類。

下面,我們首先來定義這個訪問接口。為了方便說明問題,我們在這里只列出了比較少的方法,其他的方法是很容易參照添加的。

 

     public interface DataAccess

     {

         DatabaseType DatabaseType{get;}                  //數據庫類型

          IDbConnection DbConnection{get;} //得到數據庫連接

         void Open();                    //打開數據庫連接

         void Close();                   //關閉數據庫連接

         IDbTransaction BeginTransaction();              //開始一個事務

         int ExecuteNonQuery(string commandText);       //執行Sql語句

         DataSet ExecuteDataset(string commandText);//執行Sql,返回DataSet

}

 

 

因為,DataAccess的具體實現類有一些共同的方法,所以,先從DataAccess實現一個抽象的AbstractDataAccess類,包含一些公用方法。然后,我們分別為Sql Server、Oracle和OleDb數據庫編寫三個數據訪問的具體實現類:

 

     public sealed class MSSqlDataAccess : AbstractDataAccess

     {

         ……//具體實現代碼。

     }

 

     public class OleDbDataAccess : AbstractDataAccess

     {

          ……//具體實現代碼。

     }

 

     public class OracleDataAccess : AbstractDataAccess

     {

         ……//具體實現代碼。

     }

 

 

現在我們已經完成了所要的功能,下面,我們需要創建一個Factory類,來實現自動數據庫切換的管理。這個類很簡單,主要的功能就是根據數據庫類型,返回適當的數據庫操縱類。

 

     public sealed class DataAccessFactory

     {

         private DataAccessFactory(){}

         private static PersistenceProperty defaultPersistenceProperty;

         public static PersistenceProperty DefaultPersistenceProperty

         {

              get{return defaultPersistenceProperty;}

              set{defaultPersistenceProperty=value;}

         }

         public static DataAccess CreateDataAccess(PersistenceProperty pp)

         {

              DataAccess dataAccess;

              switch(pp.DatabaseType)

              {

                   case(DatabaseType.MSSQLServer):

                       dataAccess = new MSSqlDataAccess(pp.ConnectionString);

                       break;

                   case(DatabaseType.Oracle):

                       dataAccess = new OracleDataAccess(pp.ConnectionString);

                       break;

                   case(DatabaseType.OleDBSupported):

                       dataAccess = new OleDbDataAccess(pp.ConnectionString);

                       break;

                   default:

                       dataAccess=new MSSqlDataAccess(pp.ConnectionString);

                       break;

              }

              return dataAccess;

         }

         public static DataAccess CreateDataAccess()

         {

              return CreateDataAccess(defaultPersistenceProperty);

         }

     }

 

 

好了,現在,一切都完成了,客戶端在代碼調用的時候,可能就是采用如下形式:

 

PersistenceProperty pp = new PersistenceProperty();

pp.ConnectionString = "server=127.0.0.1;uid=sa;pwd=;database=Northwind;";

pp.DatabaseType = DatabaseType. MSSQLServer;

pp.UserID = “sa”;

pp.Password = “”;

DataAccess db= DataAccessFactory.CreateDataAccess(pp)

db.Open();

……//db.需要的操作

db.Close();

 

或者,如果事先設定了DataAccessFactory的DefaultPersistenceProperty屬性,可以直接使用

DataAccess db= DataAccessFactory.CreateDataAccess()

方法創建DataAccess實例。

 

 

當數據庫發生變化的時候,只需要修改PersistenceProperty的值,客戶端不會感覺到變化,也不用去關心。這樣,實現了良好的封裝性。當然,前提是,你在編寫程序的時候,沒有用到特定數據庫的特性,例如,Sql Server的專用函數。
=================================================================================

數據庫訪問一般有不同中數據庫,比如Oracle,Sqlserver,Mysql等。 怎樣使得程序有一定的通用性。我們可以使用工廠模式來實現。具體代碼如下:

1 抽象類

using System;
 using System.Data;
 using System.Configuration;
 using System.Web;
 using System.Web.Security;
 using System.Web.UI;
 using System.Web.UI.WebControls;
 using System.Web.UI.WebControls.WebParts;
 using System.Web.UI.HtmlControls;
 
 namespace HHSCInfor.App_Code.Database
  ...{
      /// 
     /// Summary description for absDB
     /// 
     public abstract class AbsDB
      ...{
 
         public AbsDB()
          ...{
             //
             // TODO: Add constructor logic here
             //
         }
 
         //得到數據庫連接
          public abstract IDbConnection Connection ...{ get;}
 
         //打開數據庫連接
         public abstract void Open();
 
         //關閉數據庫連接
         public abstract void Close();
 
         //開始一個事務
         public abstract void BeginTrans();
 
         //提交一個事務
         public abstract void CommitTrans();
 
         //回滾一個事務
         public abstract void RollbackTrans();
 
         //執行Sql語句,沒有返回值
         public abstract void ExeSql(string strSql, string[] strParams, object[] objValues);
 
         //執行Sql,返回DataSet
         public abstract DataSet ExeSqlForDataSet(string QueryString);
 
     }

 }

2 Oracle連接的實例化

using System;
 using System.Data;
 using System.Configuration;
 using System.Web;
 using System.Web.Security;
 using System.Web.UI;
 using System.Web.UI.WebControls;
 using System.Web.UI.WebControls.WebParts;
 using System.Web.UI.HtmlControls;
 
 using System.Data.OracleClient;
 
 namespace HHSCInfor.App_Code.Database
  ...{
      /// 
     /// Summary description for OracleDB
     /// 
     internal class OracleDB : AbsDB
      ...{
          /// 
         /// 數據庫連接狀態表示
         /// 
         private string OpenFlag = "OPEN";
 
         public OracleDB()
          ...{

         }

         //數據庫連接
         private OracleConnection conn;
 
         //事務處理類
         private OracleTransaction trans;
 
         //指示當前是否正處於事務中
         private bool inTransactionFlag = false;
 
         public override IDbConnection Connection
         ...{
             get ...{ return this.conn; }
         }
 
         public OracleDB(string strConnection)
         ...{
             this.conn = new OracleConnection(strConnection);
         }
 
         public override void Open()
         ...{
             if (conn.State.ToString().ToUpper() != OpenFlag)
                 this.conn.Open();
         }
 
        public override void Close()
        ...{
             if (conn.State.ToString().ToUpper() == OpenFlag)
                 this.conn.Close();
         }
 
         public override void BeginTrans()
          ...{
             trans = conn.BeginTransaction();
             inTransactionFlag = true;
         }
 
         public override void CommitTrans()
          ...{
             trans.Commit();
             inTransactionFlag = false;
         }
 
         public override void RollbackTrans()
          ...{
             trans.Rollback();
             inTransactionFlag = false;
         }
 
 
         public override void ExeSql(string strSql, string[] strParams, object[] strValues)
          ...{
             //創建命令
             OracleCommand cmd = new OracleCommand();
 
             //設置連接
             cmd.Connection=this.conn ;
 
             //比較參數個數和參數值數組的長度是否匹配
             if ((strParams != null) && (strParams.Length != strValues.Length))
              ...{
                 throw new Exception("查詢參數和值不對應!");
             } 
 
             cmd.CommandText = strSql;
 
             if (strParams != null)
              ...{
                 for (int i = 0; i < strParams.Length; i )
                  ...{
                     cmd.Parameters.Add(strParams[i], strValues[i]);
                 }
             }
             
             //執行SQL語句
             cmd.ExecuteNonQuery();
              
         }
 
         /// 
         /// 執行數據庫查詢並將結果用數據集(DataSet)的形式返回
         /// 
         /// SQL語句
         /// 
         public override DataSet ExeSqlForDataSet(string QueryString)
         ...{
             //創建命令
             OracleCommand cmd = new OracleCommand();
 
             //設置連接
            cmd.Connection = this.conn;
 
             //傳入查詢語句
             cmd.CommandText = QueryString;
 
             //創建數據集
             DataSet ds = new DataSet();
             
             //創建適配器
             OracleDataAdapter ad = new OracleDataAdapter();
             
             //適配器命令
             ad.SelectCommand = cmd;
 
             //填充到數據集(DataSet)
             ad.Fill(ds);
 
             //返回結果數據集
             return ds;
         }
 
     }
 
 }

 

3 SqlServer的實例化(自己對照上面寫個,我也沒寫。^_^)

4 根據不同的string連接來創建不同的實例。

web.config中設置共用連接:

 using System;

 using System.Data;
 using System.Configuration;
 using System.Web;
 using System.Web.Security;
 using System.Web.UI;
 using System.Web.UI.WebControls;
 using System.Web.UI.WebControls.WebParts;
 using System.Web.UI.HtmlControls;
 
 using System.Data.OracleClient;
 
 namespace HHSCInfor.App_Code.Database
  ...{
      /// 
     /// Summary description for DBConn
     /// 
     public class DBConn
      ...{
         public DBConn()
          ...{
 
         }
 
          /// 
        /// 根據不同的字符串連接來使用不同的處理程序。
         /// 工廠方法應用(可以根據不同的strConnection創建不同的連接)。
        /// 
         /// 數據庫連接字符串
         /// 
         public static AbsDB GetDBConn()
          ...{
             // 只有一個Oracle連接時使用,如果有多個,在此添加。在Web.Config里配置。
             string strConnection = System.Configuration.ConfigurationManager.AppSettings["DBConnStr"];
 
             // 創建OracleDB連接對象
             return new OracleDB(strConnection);
 
              ///比如有sqlserver添加如下
             ///if(strConnection=?)
             ///{
             ///     return(SqlServerDB(strConnection));
             ///}
 
         }
 
     }
 }

5 測試程序:

        AbsDB conn = DBConn.GetDBConn();
 
         DataSet ds = conn.ExeSqlForDataSet("select * from sysFunction");
 
         this.Label1.Text = ds.Tables[0].Rows[2]["功能名稱"].ToString();
 
         conn.Close();
         

我的測試通過。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM