zoukankan      html  css  js  c++  java
  • 用设计模式开发通用数据库访问器 (http://dev.poptool.net/wangluo/asp.net/shujuku/11763.html)

    (http://www.uml.org.cn/sjms/200510314.htm)
          我们都希望在开发软件的时候能少写一些代码,希望能到处使用,希望不用管什么样的数据库软件都能用,我们该怎么办呢?

    我们操作数据库时用到些什么类
           一般来说,我们对数据库进行操作时都会用到一些类,下面我就对着些类做个总结:
    1.  SQLServer:
    a)         System.Data.SqlClient.SqlDataAdapter:SQL数据适配器。表示用于填充 DataSet 和更新 SQL Server 数据库的一组数据命令和一个数据库连接。无法继承此类。该类继承于System.Data.Common.DbDataAdapter和实现接口System.Data.IDbDataAdapter。采用Adapter模式设计。
    b)        System.Data.SqlClient.SqlConnection:SQL数据库连接。表示 SQL Server 数据库的一个打开的连接。无法继承此类。
    c)        System.Data.SqlClient.SqlCommandBuilder:SQL数据库命令生成器。自动生成具有以下用途的单表命令:使对 DataSet 所做的更改与关联的 SQL Server 数据库相协调。无法继承此类。采用Builder模式设计。
    另外还有一些,但是在本文中将用不到,所以这里也就不再叙述了。
    2.  Oracle:
    a)         System.Data.OracleClient.OracleDataAdapter:Oracle数据适配器。表示用于填充 DataSet 和更新Oracle数据库的一组数据命令和到数据库的连接。无法继承此类。该类继承于System.Data.Common.DbDataAdapter和实现接口System.Data.IDbDataAdapter。采用Adapter模式设计。
    b)        System.Data.OracleClient.OracleConnection:Oracle数据库连接。表示一个到Oracle数据库的打开的连接。无法继承此类。
    c)        System.Data.OracleClient.OracleCommandBuilder:Oracle数据库命令生成器。自动生成用于协调 DataSet 的更改与关联的Oracle数据库的单表命令。无法继承此类。采用Builder模式设计。
    3.  Odbc:
    a)         System.Data.Odbc.OdbcDataAdapter:Odbc类型数据数据适配器。表示数据命令集和到Odbc数据源的连接,它们用于填充 DataSet 以及更新该数据源。无法继承此类。。该类继承于System.Data.Common.DbDataAdapter和实现接口System.Data.IDbDataAdapter。采用Adapter模式设计。
    b)        System.Data.Odbc.OdbcConnection:Odbc数据库连接。表示到Odbc数据源的连接是打开的。
    c)        System.Data.Odbc.OdbcCommandBuilder:Odbc数据库命令生成器。自动生成用于协调 DataSet 的更改与关联的Odbc类型数据源的单表命令。无法继承此类。采用Builder模式设计。
    4.  OleDb:
    a)         System.Data.OleDb.OleDbDataAdapter:Odbc类型数据数据适配器。表示数据命令集和到OleDb数据源的连接,它们用于填充 DataSet 以及更新该数据源。无法继承此类。。该类继承于System.Data.Common.DbDataAdapter和实现接口System.Data.IDbDataAdapter。采用Adapter模式设计。
    b)        System.Data.OleDb.OleDbConnection:OleDb数据库连接。表示到OleDb数据源的连接是打开的。
    c)        System.Data.OleDb.OleDbCommandBuilder:OleDb数据库命令生成器。自动生成用于协调 DataSet 的更改与关联的OleDb类型数据源的单表命令。无法继承此类。采用Builder模式设计。
    我们需要什么样的数据操作器
           当然是越简单越好了,功能倒不一定要强大,够用就行。希望能支持多种数据库,使用这个操作器的程序不用再考虑是那种数据库;希望能对多个数据库操作,一个项目使用多个数据库却不对增加编程复杂度;希望支持事务,失败能够自动回滚。功能嘛,能读取数据、更新数据就可以了。
    通用数据操作器的思路
           对数据库的操作其实就是两件事:出和进。出呢就是从数据库中读取数据,进就是将数据写回数据库,包括新增数据、更新数据、删除数据。
           那么对这两个件事情该怎么做呢?
    读取数据时,我们是打开一个连接,实例化一个数据适配器然后填充数据集,关闭连接,即可。这里要注意的是,由于数据集里的表经常是数据库里多个数据表join的结果,所以你甭想让操作器自动生成查询语句,得你自己写。
    写入数据的时候,就会有一些麻烦,但因为都是执行单表操作所以你可以不用自己写SQL语句,让操作器自己生成好了。
    那么一步步怎么做呢?先打开一个数据库连接,再生成一个查询字符串,接着这两个东东实例化一个数据适配器,在生成一个CommandBuilder的实例并注册为DataAdapter的侦听器,接着配置事务。然后更新数据库,最后关闭连接。事务不能更早配置,是因为配置的事务之后便不允许数据适配器的命令为空。
    思路有了,后面就很简单了,我们只需要为每一种数据库连接定义这些操作,然后根据实际情况调用就可以了。
    当然我们不希望使用哪种数据库的由调用它的系统作为参数传入,定义在配置文件中似乎更好一些。
    由于可能有多个数据库,所以我们应当体现这种情况。比如我们可以定义默认数据库连接为“DBCon”,数据库A的连接为“ADBCon”。
    由于要实现多张表的操作,所以我们要定义一个数据集表和表名的映射。
    代码实现
           首先定义一个枚举,以指定可以支持哪些数据库:
    /// <summary>
         /// 数据库类型枚举
         /// </summary>
         public enum DBType
         {
             /// <summary>
             /// SQLServer
             /// </summary>
             SQLServer,
             /// <summary>
             /// Oracle
             /// </summary>
             Oracle,
             /// <summary>
             /// OleDB
             /// </summary>
             OleDb,
             /// <summary>
             /// Odbc
             /// </summary>
             Odbc
         }
     
         定义一个类来扩展DataTable:
         /// <summary>
         /// 用于更新数据库的数据表、库表名对
         /// </summary>
         public class DataTableExtend
         {
             /// <summary>
             /// 数据表
             /// </summary>
             public System.Data.DataTable dataTable;
     
             /// <summary>
             /// 数据表映射到数据库的表名
             /// </summary>
             public string dataTableName;
     
             /// <summary>
             /// 用于更新数据库的数据表、库表名对构造函数
             /// </summary>
             /// <param name="myTable">用于更新数据库的数据表</param>
             /// <param name="myTableName">数据表映射到数据库的表名</param>
             public DataTableExtend(System.Data.DataTable myTable, string myTableName)
             {
                  dataTable = myTable;
                  dataTableName = myTableName;
             }
         }
     
         然后写一个类来读取配置文件并获取数据库连接字符串:
         /// <summary>
         /// DBSetting 的摘要说明。
         /// </summary>
         public class DBSetting
         {
             /// <summary>
             /// 数据库连接字符串后缀
             /// </summary>
             public static string DBConnectionEnds
             {
                  get
                  {
                       return "DBCon";
                  }
             }
     
             /// <summary>
             /// 数据库类型后缀
             /// </summary>
             public static string DBTypeEnds
             {
                  get
                  {
                       return "DBType";
                  }
             }
    /// <summary>
             /// 获取指定数据库的类型
             /// </summary>
             /// <param name="dbName">指定的数据库名</param>
             /// <returns>指定数据库的类型</returns>
             public static DBType GetDBType(string dbName)
             {
                  string dbType = null;
                  dbType = AppConfig.GetAppSetting(dbName + DBTypeEnds);
                  if (dbType.ToLower() == DBType.Oracle.ToString().ToLower())
                  {
                       return DBType.Oracle;
                  }
                  if (dbType.ToLower() == DBType.Odbc.ToString().ToLower())
                  {
                       return DBType.Odbc;
                  }
                  if (dbType.ToLower() == DBType.OleDb.ToString().ToLower())
                  {
                       return DBType.OleDb;
                  }
                  else
                  {
                       return DBType.SQLServer;
                  }
             }
    /// <summary>
             /// 保存指定数据库的类型
             /// </summary>
             /// <param name="dbType">指定数据库的类型</param>
             /// <param name="dbName">指定的数据库名</param>
             public static void SaveDBType(DBType dbType,string dbName)
             {
                  AppConfig.SaveAppSetting(dbName + DBTypeEnds,dbType.ToString());
             }
    /// <summary>
             /// 获取指定数据库的连接字符串
             /// </summary>
             /// <param name="dbName">指定的数据库名</param>
             /// <returns>指定数据库的连接字符串</returns>
             public static string GetDBConnectionString(string dbName)
             {
                  return AppConfig.GetAppSetting(dbName + DBConnectionEnds);
             }
     
             /// <summary>
             /// 保存指定数据库的连接字符串
             /// </summary>
             /// <param name="connectionString">连接字符串</param>
             /// <param name="dbName">指定的数据库名</param>
             public static void SaveDBConnectionString(string connectionString, string dbName)
             {
                  AppConfig.SaveAppSetting(dbName + DBConnectionEnds,connectionString);
             }
    }
     
    接着为每一种数据库写一个类来执行针对该数据库的操作,例如针对SQL Server:
    /// <summary>
         /// 用于SQL数据源操作的类
         /// </summary>
         public class SQLExec
         {
             /// <summary>
             /// 获取数据库连接,读取由Storm.AppSetting的配置文件中dbName + "DBCon"的设置(如针对数据库Test的配置键是“TestDBCon”),若没有,则抛出异常
             /// </summary>
             /// <param name="dbName">要获取数据连接的数据库名</param>
             /// <returns>得到的数据库连接</returns>
             public static SqlConnection GetDBConnection(string dbName)
             {
                  return new SqlConnection(DBSetting.GetDBConnectionString());
             }
     
    private void ModifyDataBase(DataTableExtend[] dts, string dbName)
             {
                  //打开连接
                  SqlConnection sqlCon = GetDBConnection(dbName);
                  sqlCon.Open();
                  //根据数据表的多少生成多个数据适配器并分别生成SQL语句
                  int length = dts.Length;
                  SqlDataAdapter[] myDataAdapters = new SqlDataAdapter[length];
                  for (int i = 0; i < length; i++)
                  {
                       string selectText = GetSelectCommand(dts[i].dataTableName);
                       myDataAdapters[i] = new SqlDataAdapter(selectText, sqlCon);
                       SqlCommandBuilder cb = new SqlCommandBuilder(myDataAdapters[i]);
                       myDataAdapters[i].InsertCommand = cb.GetInsertCommand();
                       myDataAdapters[i].UpdateCommand = cb.GetUpdateCommand();
                       myDataAdapters[i].DeleteCommand = cb.GetDeleteCommand();
                  }
                  //配置事务
                  SqlTransaction myTrans;
                  myTrans = sqlCon.BeginTransaction(IsolationLevel.RepeatableRead);
                  try
                  {
                       for (int i = 0; i < length; i++)
                       {
                           myDataAdapters[i].SelectCommand.Transaction = myTrans;
                           myDataAdapters[i].InsertCommand.Transaction = myTrans;
                           myDataAdapters[i].UpdateCommand.Transaction = myTrans;
                           myDataAdapters[i].DeleteCommand.Transaction = myTrans;
                           //更新数据库
                           myDataAdapters[i].Update(dts[i].dataTable);
                       }
                       myTrans.Commit();
                       sqlCon.Close();
                       for(int i = 0; i < length ; i++)
                       {
                           dts[i].dataTable.AcceptChanges();
                       }
                  }
                  //如果失败,则自动回滚
                  catch(Exception ee)
                  {
                       myTrans.Rollback();
                       sqlCon.Close();
                       for(int i = 0; i < length ; i++)
                       {
                           dts[i].dataTable.RejectChanges();
                       }
                       throw ee;
                  }
             }
        
    /// <summary>
             /// 从数据库中读取数据
             /// </summary>
             /// <param name="dt">要承载数据的数据表</param>
             /// <param name="selectString">查询语句</param>
             public void GetData(DataTable dt, string selectString, string dbName)
             {
    SqlDataAdapter myDataAdapter = new SqlDataAdapter(selectString,SQLConfig.GetDBConnection(dbName));
                  myDataAdapter.Fill(dt);
             }
            
             //自动生成查询语句
    private static string GetSelectCommand(string dataTableName)
             {
                  string strGet = "SELECT * FROM " +dataTableName;
                  return strGet;
             }
    }
     
    然后就是写一个类来根据实际情况调用这些东东了:
    public class DatabaseExecute
         {
             private string dbName;
             /// <summary>
             /// 目标数据库
             /// </summary>
             public string DBName
             {
                  get{ return dbName; }
                  set{ dbName = value; }
             }
        
             /// <summary>
             /// 生成DatabaseExecute的实例
             /// </summary>
             public DatabaseExecute()
             {
                  dbName = null;
             }
     
             /// <summary>
             /// 用指定的目标数据库生成DatabaseModifier的实例
             /// </summary>
             /// <param name="dbName"></param>
             public DatabaseExecute(string dbName)
             {
                  this.dbName = dbName;
             }
             /// <summary>
             /// 从数据库中读取数据
             /// </summary>
             /// <param name="dt">要承载数据的数据表</param>
             /// <param name="selectString">查询语句</param>
             public void GetData(DataTable dt, string selectString)
             {
                  //操作指定数据库
                  if (DBName != null)
                  {
                       if (DBSetting.GetDBType(dbName) == DBType.SQLServer)
                       {
                           SQLExec mySQLExec = new SQLExec();
                           mySQLExec. GetData(dt, selectString, DBName);
                       }
                       else if (DBSetting.GetDBType(dbName) == DBType.Odbc)
                       {
                           OdbcExec myOdbcExec = new OdbcExec();
                           myOdbcExec. GetData(dt, selectString, DBName);
                       }
                       else if (DBSetting.GetDBType(dbName) == DBType.OleDb)
                       {
                           OleDbExec myOleDbExec = new OleDbExec();
                           mySQLExec. GetData(dt, selectString, DBName);
                       }
                       else
                       {
                           OracleExec myOracleExec = new OracleExec();
                           myOracleExec. GetData(dt, selectString, DBName);
                       }
                  }
                  //操作默认数据库
                  else
                  {
                       if (DBSetting.GetDBType(“”) == DBType.SQLServer)
                       {
                           SQLExec mySQLExec = new SQLExec();
                           mySQLExec. GetData(dt, selectString, “”);
                       }
                       else if (DBSetting.GetDBType(“”) == DBType.Odbc)
                       {
                           OdbcExec myOdbcExec = new OdbcExec();
                           myOdbcExec. GetData(dt, selectString, “”);
                       }
                       else if (DBSetting.GetDBType(dbName) == DBType.OleDb)
                       {
                           OleDbExec myOleDbExec = new OleDbExec();
                           mySQLExec. GetData(dt, selectString, “”);
                       }
                       else
                       {
                           OracleExec myOracleExec = new OracleExec();
                           myOracleExec. GetData(dt, selectString, “”);
                       }
                  }
             }
     
             /// <summary>
             /// 根据数据表组更新数据库
             /// </summary>
             /// <param name="dts">要更新的数据表组</param>
             public void ModifyDataBase(DataTableExtend[] dts)
             {
                  //操作指定数据库
                  if (dbName != null)
                  {
                       if (DBSetting.GetDBType(dbName) == DBType.SQLServer)
                       {
                           SQLExec mySQLExec = new SQLExec();
                           mySQLExec ModifyDataBase(dts,dbName);
                       }
                       else if (DBSetting.GetDBType(dbName) ==  DBType.Odbc)
                       {
                           OdbcExec mySQLExec = new OdbcExec();
                           myOdbcExec ModifyDataBase(dts,dbName);
                       }
                       else if (DBSetting.GetDBType(dbName) == DBType.OleDb)
                       {
                           OleDbExec mySQLExec = new OleDbExec();
                           myOleDbExec ModifyDataBase(dts,dbName);
                       }
                       else
                       {
                           OracleExec mySQLExec = new OracleExec();
                           myOracleExec ModifyDataBase(dts,dbName);
                       }
                  }
                  //操作默认数据库
                  else
                  {
                       if (DBSetting.GetDBType(“”) == DBType.SQLServer)
                       {
                            SQLExec mySQLExec = new SQLExec();
                           mySQLExec ModifyDataBase(dts, “”);
                       }
                       else if (DBSetting.GetDBType(dbName) ==  DBType.Odbc)
                       {
                           OdbcExec mySQLExec = new OdbcExec();
                           myOdbcExec ModifyDataBase(dts, “”);
                       }
                       else if (DBSetting.GetDBType(dbName) == DBType.OleDb)
                       {
                           OleDbExec mySQLExec = new OleDbExec();
                           myOleDbExec ModifyDataBase(dts, “”);
                       }
                       else
                       {
                           OracleExec mySQLExec = new OracleExec();
                           myOracleExec ModifyDataBase(dts, “”);
                       }
                  }
    }
     
    这样,在项目中只要引用这个DatabaseExecute类就可以了。
    最后,要注意的几点:
    1.              对于多表操作而言,因为表间有关联,所以操作的顺序很重要,本构件操作的顺序是从数据表数组的前向后处理,请千万注意表处理的顺序!
    2.              默认数据库连接由配置文件中“DBCon”的设置决定,非默认数据库连接由配置文件中“*DBCon”的设置决定,其中星号代表数据库标识
    3.              默认数据库类型由配置文件中“DBCon”的设置决定,非默认数据库类型由配置文件中“*DBCon”的设置决定,其中星号代表数据库标识
    4.              针对每一个数据库都有两个配置,分别是数据库连接和数据库类型。

  • 相关阅读:
    java 多线程面试题
    finally语句块一定会被执行吗
    redis 数据结构
    哪些可以作为GC ROOT
    mybatis 源码分析--日志分析
    mybatis selectKey
    spring cache 和redis
    kafka是如何保证消息不被重复消费的
    kafka面试题及答案
    浅谈:2019 前端面试题
  • 原文地址:https://www.cnblogs.com/snowball/p/444708.html
Copyright © 2011-2022 走看看