熱點推薦:
您现在的位置: 電腦知識網 >> 操作系統 >> Windows系統管理 >> 正文

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

2013-11-11 21:29:53  來源: Windows系統管理 

  在應用程序的設計中數據庫的訪問是非常重要的我們通常需要將對數據庫的訪問集中起來以保證良好的封裝性和可維護性Net中數據庫的訪問對於微軟自家的SqlServer和其他數據庫(支持OleDb)采用不同的訪問方法這些類分別分布於SystemDataSqlClient和SystemDataOleDb名稱空間中微軟後來又推出了專門用於訪問Oracle數據庫的類庫我們希望在編寫應用系統的時候不因這麼多類的不同而受到影響能夠盡量做到數據庫無關當後台數據庫發生變更的時候不需要更改客戶端的代碼
  
    有的時候為了性能和其他原因我們也希望提供對數據庫訪問的緩存特別是數據庫連接的緩存雖然微軟給我們內置了數據庫緩存但是自己控制緩存無疑可以提供更大的靈活性和效率
  
    這就需要我們在實際開發過程中將這些數據庫訪問類再作一次封裝這裡介紹一種在實際應用中得到了非常好的效果的實作策略Factory和Silgleton設計模式是使用的主要方法
  
    我們先來看看Factory的含義定義一個用於創建對象的接口讓子類決定實例化哪一個類Factory Method使一個類的實例化延遲到其子類我們這裡可能會處理對多種數據庫的操作因此需要首先定義一個操縱數據庫的接口然後根據數據庫的不同由類工廠決定實例化哪個類
  
    下面我們首先來定義這個訪問接口為了方便說明問題我們為這個類定義了比較少的方法其他的方法是很容易參照添加的同時注意我這裡使用了abstract class來定義這個訪問接口而不是interface理由在後面可以看到
  
  public abstract class DBOperator
   {
   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(); //回滾一個事務
   public abstract void exeSql(string strSqlstring[] strParamsobject[] objValues);
   //執行Sql語句沒有返回值
   public abstract DataSet exeSqlForDataSet(string QueryString);//執行Sql返回DataSet
   }
  
  
  
    然後我們分別為Sql Server和OleDb數據庫編寫兩個數據訪問的具體實現類
  
    Sql Server的數據庫訪問類
  
  internal class SqlDBOperator: DBOperator
   {
   private SqlConnection conn; //數據庫連接
   private SqlTransaction trans; //事務處理類
   private bool inTransaction=false; //指示當前是否正處於事務中
   public override IDbConnection Connection
   {
     get{return nn;}
   }
   public SqlDBOperator(string strConnection)
   {
     nn= new SqlConnection(strConnection);
   }
   public override void Open()
   {
     if(connStateToString()ToUpper()!=OPEN)
       nnOpen();
   }
   public override void Close()
   {
     if (connStateToString()ToUpper()==OPEN)
   nnClose();
   }
   public override void BeginTrans()
   {
     trans=connBeginTransaction() ;
       inTransaction=true;
   }
   public override void CommitTrans()
   {
     transCommit();
       inTransaction=false;
   }
   public override void RollbackTrans()
   {
     transRollback();
       inTransaction=false;
   }
   public override void exeSql(string strSqlstring[] strParamsobject[] strValues)
   {
     SqlCommand cmd=new SqlCommand();
     cmdConnection=nn ;
     if(inTransaction)
       cmdTransaction=trans;
     if((strParams!=null)&&(strParamsLength!=strValuesLength) )
   throw new ParamValueNotMatchException(查詢參數和值不對應!);
   cmdCommandText=strSql;
     if(strParams!=null)
   {
     for(int i=;i   cmd.Parameters.Add(strParams[i],strValues[i]);
   }
     cmd.ExecuteNonQuery();
   }
   public override DataSet exeSqlForDataSet(string QueryString)
   {
     SqlCommand cmd=new SqlCommand();
   cmd.Connection=nn ;
     if(inTransaction)
    cmd.Transaction=trans;
     DataSet ds = new DataSet();
     SqlDataAdapter ad = new SqlDataAdapter();
     cmd.CommandText=QueryString;
     ad.SelectCommand =cmd;
     ad.Fill(ds);
     return ds;
     }
      }
  
  
  
    OleDb數據庫操作的類同Sql Server數據庫操作的類非常相似,只是把相應的Sql類替換成OleDb類。TW.WinGWIt.cOm需要注意的是,因為OleDb和Sql Server的參數傳遞方式不一致,所以,這裡需要做一點小小的轉換,將"@參數名"類型的參數轉換成"?",這個細節希望讀者能夠注意到。代碼如下:
  
  internal class OleDBOperator : DBOperator
   {
   private OleDbConnection conn;
   private OleDbTransaction trans;
   private bool inTransaction=false;
   public OleDBOperator(string strConnection)
   {
    nn= new OleDbConnection(strConnection);
   }
   public override IDbConnection Connection
   {
    get{return nn;}
   }
   public override void Open()
   {
   if(conn.State.ToString().ToUpper()!="OPEN")
   nn.Open();
   }
   public override void Close()
   {
     if (conn.State.ToString().ToUpper()=="OPEN")
   nn.Close();
   }
   public override void BeginTrans()
   {
     trans=conn.BeginTransaction() ;
      inTransaction=true;
   }
   public override void CommitTrans()
   {
     trans.Commit();
     inTransaction=false;
   }
   public override void RollbackTrans()
   {
     trans.Rollback();
     inTransaction=false;
   }
   public override void exeSql(string strSql,string[] strParams,object[] strValues)
   {
   OleDbCommand cmd=new OleDbCommand();
    cmd.Connection=nn ;
   if(inTransaction)
     cmd.Transaction=trans;
   if((strParams!=null)&&(strParams.Length!=strValues.Length) )
   throw new ParamValueNotMatchException("查詢參數和值不對應!");
   cmd.CommandText=this.ChangeQueryString(strSql);
   if(strParams!=null)
   {
   for(int i=0;i   cmd.Parameters.Add(strParams[i],strValues[i]);
   }
     cmd.ExecuteNonQuery();
   }
   public override DataSet exeSqlForDataSet(string QueryString)
   {
     OleDbCommand cmd=new OleDbCommand();
   cmd.Connection=nn ;
     if(inTransaction)
       cmd.Transaction=trans;
     DataSet ds = new DataSet();
     OleDbDataAdapter ad = new OleDbDataAdapter();
   cmd.CommandText=QueryString;
     ad.SelectCommand =cmd;
     ad.Fill(ds);
     return ds;
     }
   }
  
  
  
    現在我們已經完成了所要的功能,下面,我們需要創建一個Factory類,來實現自動數據庫切換的管理。這個類很簡單,主要的功能就是根據數據庫連接字符串,判斷使用什麼數據庫,然後,返回適當的數據庫操縱類。在這裡,判斷的方法很簡單,只是根據兩種數據庫連接字符串的不同來判斷。在實際中,隨著數據庫類的增加,判斷的方法可能會有所變化,讀者應當根據自己的實際情況來做相應的調整。
  
  public class DBOperatorFactory
   {
   public static DBOperator GetDBOperator(string strConnection)
   {
    if(strConnection.IndexOf("provider=")<0) //SqlServer
   {
    return new SqlDB
From:http://tw.wingwit.com/Article/os/xtgl/201311/8590.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.