用设计模式开发通用数据库操作器 (转)[@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/,如需转载,请注明出处,否则将追究法律责任。
下一篇:
我就是程序,程序就是我吗? (转)
请登录后发表评论
登录
全部评论
<%=items[i].createtime%>
<%=items[i].content%>
<%if(items[i].items.items.length) { %>
<%for(var j=0;j
<%}%> <%if(items[i].items.total > 5) { %>
<%}%>
<%=items[i].items.items[j].createtime%>
<%=items[i].items.items[j].username%> 回复 <%=items[i].items.items[j].tousername%>: <%=items[i].items.items[j].content%>
还有<%=items[i].items.total-5%>条评论
) data-count=1 data-flag=true>点击查看
<%}%>
转载于:http://blog.itpub.net/10794571/viewspace-974705/