日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

使用设计模式构建通用数据库访问类

發(fā)布時間:2023/12/4 数据库 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用设计模式构建通用数据库访问类 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
在應用程序的設計中,數(shù)據(jù)庫的訪問是非常重要的,我們通常需要將對數(shù)據(jù)庫的訪問集中起來,以保證良好的封裝性和可維護性。在.Net中,數(shù)據(jù)庫的訪問,對于微軟自家的SqlServer和其他數(shù)據(jù)庫(支持OleDb),采用不同的訪問方法,這些類分別分布于System.Data.SqlClient和System.Data.OleDb名稱空間中。微軟后來又推出了專門用于訪問Oracle數(shù)據(jù)庫的類庫。我們希望在編寫應用系統(tǒng)的時候,不因這么多類的不同而受到影響,能夠盡量做到數(shù)據(jù)庫無關,當后臺數(shù)據(jù)庫發(fā)生變更的時候,不需要更改客戶端的代碼。
??
??  有的時候,為了性能和其他原因,我們也希望提供對數(shù)據(jù)庫訪問的緩存,特別是數(shù)據(jù)庫連接的緩存。雖然微軟給我們內(nèi)置了數(shù)據(jù)庫緩存,但是,自己控制緩存,無疑可以提供更大的靈活性和效率。
??
??  這就需要我們在實際開發(fā)過程中將這些數(shù)據(jù)庫訪問類再作一次封裝。這里,介紹一種在實際應用中得到了非常好的效果的實作策略。Factory和Silgleton設計模式是使用的主要方法。
??
??  我們先來看看Factory的含義:定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。Factory Method使一個類的實例化延遲到其子類。我們這里可能會處理對多種數(shù)據(jù)庫的操作,因此,需要首先定義一個操縱數(shù)據(jù)庫的接口,然后,根據(jù)數(shù)據(jù)庫的不同,由類工廠決定實例化哪個類。
??
??  下面,我們首先來定義這個訪問接口。為了方便說明問題,我們?yōu)檫@個類定義了比較少的方法,其他的方法是很容易參照添加的。同時注意,我這里使用了abstract class來定義這個訪問接口,而不是interface,理由在后面可以看到。
??
??public abstract class DBOperator
?? {
?? public abstract IDbConnection Connection{get;} //得到數(shù)據(jù)庫連接
?? public abstract void Open(); //打開數(shù)據(jù)庫連接
?? public abstract void Close(); //關閉數(shù)據(jù)庫連接
?? public abstract void BeginTrans(); //開始一個事務
?? public abstract void CommitTrans(); //提交一個事務
?? public abstract void RollbackTrans(); //回滾一個事務
?? public abstract void exeSql(string strSql,string[] strParams,object[] objValues);
?? //執(zhí)行Sql語句,沒有返回值
?? public abstract DataSet exeSqlForDataSet(string QueryString);//執(zhí)行Sql,返回DataSet
?? }
??
??
??
??  然后,我們分別為Sql Server和OleDb數(shù)據(jù)庫編寫兩個數(shù)據(jù)訪問的具體實現(xiàn)類:
??
??  Sql Server的數(shù)據(jù)庫訪問類:
??
??internal class SqlDBOperator: DBOperator
?? {
?? private SqlConnection conn; //數(shù)據(jù)庫連接
?? private SqlTransaction trans; //事務處理類
?? private bool inTransaction=false; //指示當前是否正處于事務中
?? public override IDbConnection Connection
?? {
??   get{return this.conn;}
?? }
?? public SqlDBOperator(string strConnection)
?? {
??   this.conn= new SqlConnection(strConnection);
?? }
?? public override void Open()
?? {
??   if(conn.State.ToString().ToUpper()!="OPEN")
??     this.conn.Open();
?? }
?? public override void Close()
?? {
??   if (conn.State.ToString().ToUpper()=="OPEN")
?? this.conn.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)
?? {
??   SqlCommand cmd=new SqlCommand();
??   cmd.Connection=this.conn ;
??   if(inTransaction)
??     cmd.Transaction=trans;
??   if((strParams!=null)&&(strParams.Length!=strValues.Length) )
?? throw new ParamValueNotMatchException("查詢參數(shù)和值不對應!");
?? cmd.CommandText=strSql;
??   if(strParams!=null)
?? {
??   for(int i=0;i<strParams.Length;i++)
?? cmd.Parameters.Add(strParams[i],strValues[i]);
?? }
??   cmd.ExecuteNonQuery();
?? }
?? public override DataSet exeSqlForDataSet(string QueryString)
?? {
??   SqlCommand cmd=new SqlCommand();
?? cmd.Connection=this.conn ;
??   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數(shù)據(jù)庫操作的類同Sql Server數(shù)據(jù)庫操作的類非常相似,只是把相應的Sql類替換成OleDb類。需要注意的是,因為OleDb和Sql Server的參數(shù)傳遞方式不一致,所以,這里需要做一點小小的轉(zhuǎn)換,將"@參數(shù)名"類型的參數(shù)轉(zhuǎn)換成"?",這個細節(jié)希望讀者能夠注意到。代碼如下:
??
??internal class OleDBOperator : DBOperator
?? {
?? private OleDbConnection conn;
?? private OleDbTransaction trans;
?? private bool inTransaction=false;
?? public OleDBOperator(string strConnection)
?? {
??  this.conn= new OleDbConnection(strConnection);
?? }
?? public override IDbConnection Connection
?? {
??  get{return this.conn;}
?? }
?? public override void Open()
?? {
?? if(conn.State.ToString().ToUpper()!="OPEN")
?? this.conn.Open();
?? }
?? public override void Close()
?? {
??   if (conn.State.ToString().ToUpper()=="OPEN")
?? this.conn.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=this.conn ;
?? if(inTransaction)
??   cmd.Transaction=trans;
?? if((strParams!=null)&&(strParams.Length!=strValues.Length) )
?? throw new ParamValueNotMatchException("查詢參數(shù)和值不對應!");
?? cmd.CommandText=this.ChangeQueryString(strSql);
?? if(strParams!=null)
?? {
?? for(int i=0;i<strParams.Length;i++)
?? cmd.Parameters.Add(strParams[i],strValues[i]);
?? }
??   cmd.ExecuteNonQuery();
?? }
?? public override DataSet exeSqlForDataSet(string QueryString)
?? {
??   OleDbCommand cmd=new OleDbCommand();
?? cmd.Connection=this.conn ;
??   if(inTransaction)
??     cmd.Transaction=trans;
??   DataSet ds = new DataSet();
??   OleDbDataAdapter ad = new OleDbDataAdapter();
?? cmd.CommandText=QueryString;
??   ad.SelectCommand =cmd;
??   ad.Fill(ds);
??   return ds;
??   }
?? }
??
??
??
??  現(xiàn)在我們已經(jīng)完成了所要的功能,下面,我們需要創(chuàng)建一個Factory類,來實現(xiàn)自動數(shù)據(jù)庫切換的管理。這個類很簡單,主要的功能就是根據(jù)數(shù)據(jù)庫連接字符串,判斷使用什么數(shù)據(jù)庫,然后,返回適當?shù)臄?shù)據(jù)庫操縱類。在這里,判斷的方法很簡單,只是根據(jù)兩種數(shù)據(jù)庫連接字符串的不同來判斷。在實際中,隨著數(shù)據(jù)庫類的增加,判斷的方法可能會有所變化,讀者應當根據(jù)自己的實際情況來做相應的調(diào)整。
??
??public class DBOperatorFactory
?? {
?? public static DBOperator GetDBOperator(string strConnection)
?? {
??  if(strConnection.IndexOf("provider=")<0) //SqlServer
?? {
??  return new SqlDBOperator(strConnection);
?? }
??  else //other database
?? {
??  return new OleDBOperator(strConnection);
?? }
?? }
?? }
??
??
??
??  好了,現(xiàn)在,一切都完成了,客戶端在代碼調(diào)用的時候,可能就是采用如下形式:
??
??DBOperator db=DBOperatorFactory.GetDBOperator(strConnection)
??db.Open();
??db.需要的操作
??db.Close();
??
??或者:
??DBOperator db=DBOperatorFactory.GetDBOperator(strConnection)
??db.Open();db.BeginTrans();
??try
??{
??db.需要的操作
??db.CommitTrans();
??}
??catch
??{
??db.RollbackTrans();
??}
??db.Close();
??
??
??
??  當數(shù)據(jù)庫發(fā)生變化的時候,DBOperatorFactory會根據(jù)數(shù)據(jù)庫連接字符串自動調(diào)用相應的類,客戶端不會感覺到變化,也不用去關心。這樣,實現(xiàn)了良好的封裝性。當然,前提是,你在編寫程序的時候,沒有用到特定數(shù)據(jù)庫的特性,例如,Sql Server的專用函數(shù)。
??
??  實際上,Factory模式也可以不使用Factory類來實現(xiàn),而是讓接口抽象類自己來管理,這可以稱作自管理的Factory,是Factory模式的一種變形。這么做的好處,是可以免去一個Factory類,使代碼更加簡練。這么做,我們需要對DBOperator類做一些改變,增加一個Instance方法。這也是對DBOperator采用抽象類而不是接口的原因(接口的方法不能有實現(xiàn)),代碼如下:
??
??public static DBOperator Instance(string strConnection)
?? {
?? if(strConnection.IndexOf("provider=")<0) //SqlServer
?? {
?? return new SqlDBOperator(strConnection);
?? }
?? else //other database
?? {
?? return new OleDBOperator(strConnection);
?? }
?? }
??
??
??
??  然后,客戶端代碼就可能是類似于下面的形式:
??
??DBOperator db= DBOperator.Instance(strConnection)
??db.Open();
??db.需要的操作
??db.Close();
??
??
??
??  下面來看看連接池的做法,方法就是Singleton。
??
??  先看Singleton模式的經(jīng)典含義:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。推而廣之,當我們需要精確控制類在系統(tǒng)中的實例的個數(shù)的時候,就可以使用Singleton模式。現(xiàn)在,我們需要構(gòu)建一個緩沖池,保存數(shù)據(jù)庫類的實例,正好是Singleton模式發(fā)揮作用的時候。
??
??  我們?nèi)匀蛔孌BOperator類自己來管理這個緩沖池,為了實現(xiàn)這個目的,我們需要對DBOperator類做一些變化:
??
??  首先,增加兩個變量:
??
?? static DBOperator[] ConnectionPool=new
?? DBOperator[int.Parse(ConfigurationSettings.AppSettings["PoolCount"])];
?? static int CurrentPosition=-1;
??
??
??
??  然后,對Instance方法做一些改變:
??
??public static DBOperator Instance(string strConnection)
?? {
?? if(ApplicationConfiguration.PooledConnectionCount<1) //沒有緩沖
?? {
?? return CreateNewDBOperator(strConnection);
?? }
?? else
?? {
?? CurrentPosition++;
?? if(CurrentPosition==ApplicationConfiguration.PooledConnectionCount)
?? CurrentPosition=0;
?? if(ConnectionPool[CurrentPosition]==null)
?? {
?? ConnectionPool[CurrentPosition]=CreateNewDBOperator(strConnection);
?? }
?? return ConnectionPool[CurrentPosition];
?? }
?? }
?? private static DBOperator CreateNewDBOperator(string strConnection)
?? {
?? if(strConnection.IndexOf("provider=")<0) //SqlServer
?? {
?? return new SqlDBOperator(strConnection);
?? }
?? else //other database
?? {
?? return new OleDBOperator(strConnection);
?? }
?? }
??
??
??
??
??  這里使用的算法比較簡單,只是為了能夠比較清楚地說明問題,讀者應當能夠在實際使用過程中,實現(xiàn)更好的算法。
??
??  以上,介紹了一種通用數(shù)據(jù)庫操作類的實現(xiàn)設計方法,希望能夠?qū)Υ蠹矣兴鶈l(fā)。筆者設計Websharp中間件的時候,在數(shù)據(jù)庫處理層,采用了上面的方法,取得了很好的效果。

總結(jié)

以上是生活随笔為你收集整理的使用设计模式构建通用数据库访问类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。