自建工具集开发文档------数据库操作(1.0.0.1)
版本号
创建人
创建时间
备注
1.0.0.1
穆仕途
2003-12-21
草稿
关键字:C#、工具集、数据库、连接池
正文:
.Net Framework提供ADO.NET功能强大,在此写这个数据库处理类的主要目的是为了把数据库处理集中处理,自动生成简单的SQL语句,对上层隐藏数据库细节,方便于扩展和维护。并且可以把它放到别的系统中而不需要做程序上的改动,只需要修改部分配置信息而已。
设计目标
1. 实现数据库连接池,并可配置池的大小,配置是否使用连接池。
2. 自动生成插入、删除、更新的SQL语句。
3. 自动生成简单的查询、聚合查询的SQL语句。
4. 通过配置可以选择为不同数据库实现的操作类集合。
5. 对上层隐藏数据库细节,隐藏数据源细节。
6. 从数据库自动导出数据库结构,并存放于XML文件供程序使用。
设计思想:
主要思想是:把数据库相关的所有操作全部封装起来,内部的实现采用自动生成SQL语句,对表和列的引用都采用别名,尽量分离各种耦合,用配置文件来减少重用或者修改所来的工作量。比如对表的字段名称的修改将不会影响到工具和系统的变动。
目前只实现了Microsoft SQL Server2000的操作。
结构说明:
主要包括一个接口和4个类,他们的关系如下图所示:
1. IDBase接口类:定义了一系列数据库操作的公共方法,针对某种数据库或别的数据源写的操作类都必须实现这个借口。
2. SqlDBase类:实现所有的数据库操作,包括插入、更新、删除、查询、执行存储过程等,实现上面的接口定义的方法。
3. DbaseFactory类:定义了一个工厂,根据系统配置文件中配置的信息来决定调用那一个数据库操作类,在本系统中,只实现了SQL Server中的数据库操作类,可以扩展至别的数据库操作。使用了工厂(Factory)模式。
4. DBPool类:实现了数据库连接池,可以从中获取可用的数据库连接,里面使用了单件(Singleton)模式。
5. ownConnection类:封装了框架提供的SqlConnection对象,增加了一层状态信息,主要供DBPool类使用。
下面逐个介绍这些类。
ownConnection类:
封装了框架提供的SqlConnection对象,主要目的是为连接加入一个自定义的状态。在数据库连接池中将存放多个连接对象,对连接对象的操作将主要参照这里自定义的状态。
字段:
private string _connectionString = Constant.Data_Base_Connection;
private SqlConnection _myConnection = new SqlConnection();
private Constant.ConnectionStatus _status;
* _connectionString:数据库连接字符串,用Constant类的常量来构造。
* _myConnection:数据库连接,SqlConnection对象
* _status状态,取值由常量类中的一个枚举型确定,有这几种值Free、Busy、Death。
方法:
private bool OpenConnection()
public ownConnection()
public SqlConnection GetConnection()
public void SetToBusy()
public void ResetConnection()
* OpenConnection():私有方法,根据字段connectionString来打开数据库连接,打开失败则抛出异常。
* ownConnection():公共构造函数,在内部调用方法OpenConnection(),设置本实例的状态,打开成功设为Free,否则设为Death。
* GetConnection():获取可用的数据库连接,返回一个SqlConnection对象。
* SetToBusy():把本实例的状态设置为Busy,标志本连接正在使用中。
* ResetConnection():重设数据库连接,如果连接状态无效,则调用OpenConnection()重新打开连接。
DBPool类
数据库连接池类,使用了Singleton模式来保证实例的唯一性,根据配置文件中设置的连接池的大小,维护一个连接对象数组,给数据库操作类提供可用的数据库连接。
字段:
private static ArrayList DBPools = new ArrayList(Constant.Init_Pool_Size)
private static int initPoolSize;
private static int validConnectionCount;
private static volatile DBPool instance = new DBPool();
private static object syncRoot = new object();
由于DBPool类在系统中只能有一个实例,所以,字段都标记为static。这些字段将长驻内存,并且在系统启动的时候就初始化。
* DBPools:存放数据库连接的一个静态数组ArrayList,大小为系统配置文件中定义的连接池大小。
* initPoolSize:连接池大小,值和系统配置文件中定义的池的大小一致。
* validConnectionCount:连接池中可用的连接数,为0时代表没有可用连接,初始为0。
* instance:连接池对象,初始化时就实例化,保证了系统启动的时候就实例化连接池对象,这是单件模式的一部分,后面将专门讲述我对这个模式的理解。
* syncRoot:初始化一个同步对象,在单件模式中防止死锁,将在后面讲述。
方法:
private static bool InitPool()
private DBPool()
public static DBPool Instance
public static ownConnection GetConnection()
public static SqlConnection GetConnection(string conName)
* InitPool():根据数据库连接池大小,初始化数据库连接池,并且返回初始化成败标志,目前的程序皆返回成功,发生异常的时候将由上层处理。
* DBPool():私有构造器,防止被实例化。设置字段,调用InitPool()初始化连接池。
* Instance:获取数据库连接池的实例。
* GetConnection():获取一个数据库连接。
* GetConnection(string conName):重载上面的方法,这里将根据参数决定是否从连接池中取数据。这样实现的考虑是:可能一个系统会对应几个数据库,而连接池中放的都是基于一个数据库的连接,别的数据库连接将这个重载的方法来获取。
Singleton模式的应用,代码如下图:
private static volatile DBPool instance = new DBPool();
private static object syncRoot = new object();
private DBPool()
{
try
{
initPoolSize = Constant.Init_Pool_Size;
validConnectionCount = 0;
InitPool();
}
catch(utilException e)
{
}
catch(Exception e)
{
utilException myException = new utilException(e, "");
}
}
public static DBPool Instance
{
get
{
if(instance == null)
{
lock(syncRoot)
{
if(instance == null)
instance = new DBPool();
}
}
return instance;
}
}
静态字段instance的声明,将调用私有构造器,当系统启动的时候,就有了一个数据库连接池对象,当需要使用连接池对象的时候,通过静态属性Instance来访问,主要说明一下这个属性内部的实现。
1. 系统启动的时候,就应该存在一个连接池实例,如果不为空则直接返回实例,否则
2. lock(syncRoot)确保当一个线程位于代码的临界区时,另一个线程不进入临界区,进行互斥的访问,防止同时的请求而生成多个实例。
这样就保证了数据库连接池实例的唯一性,也是Singleton模式的典型的应用
连接池的维护
1. 初始化连接池的时候按连接池大小建立数据库连接;
2. 用户用GetConnection()请求一个连接的时候,在连接池里面遍历数据库连接对象,找到可用的数据库连接后,把连接对象的状态设置为Busy,然后返回连接对象;
3. 当连接池内没有可用的连接时,则遍历数据库连接对象,把所有不可用的连接对象用ResetConnection()来重新打开连接。
4. 继续执行步骤2,返回可用的连接对象;如果仍然没有可用连接返回,执行步骤5
5. 抛出一个异常,说明连接全部被占用。