zoukankan      html  css  js  c++  java
  • 使用设计模式构建通用数据库访问类


    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 strSql,string[] strParams,object[] objValues); 
       
    //执行Sql语句,没有返回值 
       public abstract DataSet exeSqlForDataSet(string QueryString);
      
    //执行Sql,返回DataSet 
       } 

    我们编写数据访问的具体实现类:
    Sql Server的数据库访问类:  

    internal class SqlDBOperator: DBOperator  
      {    
             
    private SqlConnection conn;
             
    //数据库连接
             private SqlTransaction trans;
             
    //事务处理类    
             private bool inTransaction=false;
             
    //指示当前是否正处于事务中    
      public override IDbConnection Connection  
        {      
         
    get{
            
    return this.conn;
            } 
        } 
       
    //SQL数据库的连接方法  
      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;   
        }
      
    //执行SQL语句的操作,无返回值    
      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("查询参数和值不对应!");  
         cmd.CommandText
    =strSql;    
       
    if(strParams!=null)   
           {    
          
    for(int i=0;i<strParams.Length;i++)  
             cmd.Parameters.Add(strParams[i],strValues[i]); 
           }   
       cmd.ExecuteNonQuery();  
        }
     
    //重载执行SQL语句的操作,返回数据集 
      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的数据库访问类:

    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("查询参数和值不对应!"); 
           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; 
         } 
       } 
    我们需要创建一个Factory类,来实现自动数据库切换的管理。这个类很简单,主要的功能就是根据数据库连接字符串,判断使用什么数据库,然后,返回适当的数据库操纵类。在这里,判断的方法很简单,只是根据两种数据库连接字符串的不同来判断。在实际中,随着数据库类的增加,判断的方法可能会有所变化。 
     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); 
            } 
         } 
       } 
    客户端在代码调用的时候,可能就是采用如下形式:
     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(); 
    当数据库发生变化的时候,DBOperatorFactory会根据数据库连接字符串自动调用相应的类,客户端不会感觉到变化,也不用去关心。这样,实现了良好的封装性。当然,前提是,你在编写程序的时候,没有用到特定数据库的特性,例如,Sql Server的专用函数。
       实际上,Factory模式也可以不使用Factory类来实现,而是让接口抽象类自己来管理,这可以称作自管理的Factory,是Factory模式的一种变形。这么做的好处,是可以免去一个Factory类,使代码更加简练。这么做,我们需要对DBOperator类做一些改变,增加一个Instance方法。这也是对DBOperator采用抽象类而不是接口的原因(接口的方法不能有实现),代码如下: 

    public static DBOperator Instance(string strConnection) 
       {   
         
    if(strConnection.IndexOf("provider=")<0//SqlServer 
           { 
              
    return new SqlDBOperator(strConnection);    
           } 
          
    else //other database 
           {
               
    return new OleDBOperator(strConnection);   
           } 
       } 
    Singleton设计模式
      含义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。推而广之,当我们需要精确控制类在系统中的实例的个数的时候,就可以使用Singleton模式。现在,我们需要构建一个缓冲池,保存数据库类的实例,正好是Singleton模式发挥作用的时候

    我们仍然让DBOperator类自己来管理这个缓冲池,为了实现这个目的,我们需要对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);   
         } 
       } 

    这样就完成了!


  • 相关阅读:
    算法设计和分析(Prim算法构建最小生成树)
    寒假第二阶段集训第6天
    2.4 综合训练
    1月18日 LCA专项训练
    易班易喵喵话题动态自动统计
    P2590 [ZJOI2008]树的统计
    P3038 [USACO11DEC]牧草种植Grass Planting
    2157: 旅游
    P2787 语文1(chin1)- 理理思维
    F. Make Them Similar
  • 原文地址:https://www.cnblogs.com/HeroBeast/p/884566.html
Copyright © 2011-2022 走看看