分享
 
 
 

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

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

我们都希望在开发软件的时候能少写一些代码,希望能到处使用,希望不用管什么样的数据库软件都能用,我们该怎么办呢?

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

一般来说,我们对数据库进行操作时都会用到一些类,下面我就对着些类做个总结:

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. 针对每一个数据库都有两个配置,分别是数据库连接和数据库类型。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有