用设计模式开发通用数据库操作器 (转)

用设计模式开发通用数据库操作器 (转)[@more@]
  我们都希望在开发 软件的时候能少写一些代码,希望能到处使用,希望不用管什么样的 数据库软件都能用,我们该怎么办呢?

我们操作数据库时用到些什么类

  一般来说,我们对数据库进行操作时都会用到一些类,下面我就对着些类做个总结:
1.  sqlServer:
a)  System.Data.SqlClient.SqlDataAdapter SQL数据适配器。表示用于填充 2003/MS.MSDNQTR.2003FEB.2052/cpref/html/frlrfsystemdatadatasetclasstopic.htm">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”。
由于要实现多张表的操作,所以我们要定义一个数据集表和表名的映射。

代码实现

  首先定义一个枚举,以指定可以支持哪些数据库: ///   /// 数据库类型枚举   ///   public enum DBType   {   ///   /// SQLServer   ///   SQLServer,   ///   /// Oracle   ///   Oracle,   ///   /// OleDB   ///   OleDb,   ///   /// Odbc   ///   Odbc
  }
 
  定义一个类来扩展DataTable:   ///   /// 用于更新数据库的数据表、库表名对   ///   public class DataTableExtend   {   ///   /// 数据表   ///   public System.Data.DataTable dataTable;     ///   /// 数据表映射到数据库的表名   ///   public string dataTableName;     ///   /// 用于更新数据库的数据表、库表名对构造 函数   ///   /// 用于更新数据库的数据表   /// 数据表映射到数据库的表名   public DataTableExtend(System.Data.DataTable myTable, string myTableName)   {   dataTable = myTable;   dataTableName = myTableName;   }
  }
 
  然后写一个类来读取配置文件并获取数据库连接字符串:   ///   /// DBSetting 的摘要说明。   ///   public class DBSetting   {   ///   /// 数据库连接字符串后缀   ///   public static string DBConnectionEnds   {   get   {   return "DBCon";   }   }     ///   /// 数据库类型后缀   ///   public static string DBTypeEnds   {   get   {   return "DBType";   }
  } ///   /// 获取指定数据库的类型   ///   /// 指定的数据库名   /// 指定数据库的类型   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;   }
  } ///   /// 保存指定数据库的类型   ///   /// 指定数据库的类型   /// 指定的数据库名   public static void SaveDBType(DBType dbType,string dbName)   {   AppConfig.SaveAppSetting(dbName + DBTypeEnds,dbType.ToString());
  } ///   /// 获取指定数据库的连接字符串   ///   /// 指定的数据库名   /// 指定数据库的连接字符串   public static string GetDBConnectionString(string dbName)   {   return AppConfig.GetAppSetting(dbName + DBConnectionEnds);
  }
    ///   /// 保存指定数据库的连接字符串   ///   /// 连接字符串   /// 指定的数据库名   public static void SaveDBConnectionString(string connectionString, string dbName)   {   AppConfig.SaveAppSetting(dbName + DBConnectionEnds,connectionString);
  }
}
 
接着为每一种数据库写一个类来执行针对该数据库的操作,例如针对SQL Server: ///   /// 用于SQL数据源操作的类   ///   public class SQLExec
  {   ///   /// 获取数据库连接,读取由Storm.AppSetting的配置文件中dbName + "DBCon"的设置(如针对数据库Test的配置键是“TestDBCon”),若没有,则抛出异常   ///   /// 要获取数据连接的数据库名   /// 得到的数据库连接   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;   }
  }
  ///   /// 从数据库中读取数据   ///   /// 要承载数据的数据表   /// 查询语句
  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;   ///   /// 目标数据库   ///   public string DBName   {   get{ return dbName; }   set{ dbName = value; }   }     ///   /// 生成DatabaseExecute的实例   ///   public DatabaseExecute()   {   dbName = null;   }     ///   /// 用指定的目标数据库生成DatabaseModifier的实例   ///   ///   public DatabaseExecute(string dbName)   {   this.dbName = dbName;   }   ///   /// 从数据库中读取数据   ///   /// 要承载数据的数据表   /// 查询语句   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, “”);   }   }   }     ///   /// 根据数据表组更新数据库   ///   /// 要更新的数据表组   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.  针对每一个数据库都有两个配置,分别是数据库连接和数据库类型。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10794571/viewspace-974705/,如需转载,请注明出处,否则将追究法律责任。

user_pic_default.png
请登录后发表评论 登录
全部评论
<%=items[i].createtime%>

<%=items[i].content%>

<%if(items[i].items.items.length) { %>
<%for(var j=0;j
<%=items[i].items.items[j].createtime%> 回复

<%=items[i].items.items[j].username%>   回复   <%=items[i].items.items[j].tousername%><%=items[i].items.items[j].content%>

<%}%> <%if(items[i].items.total > 5) { %>
还有<%=items[i].items.total-5%>条评论 ) data-count=1 data-flag=true>点击查看
<%}%>
<%}%>
<%}%>

转载于:http://blog.itpub.net/10794571/viewspace-974705/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值