using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;
using System.Threading;
using System.Collections;
namespace DateBaseConnectionPool
{
///
/// 数据库连接池,默认数据库连接方案是ODBC
///
public class Pool : IDisposable
{
#region 变量定义
//属性
private int _realFormPool;//连接池中存在的实际连接数(包含失效的连接)
private int _potentRealFormPool;//连接池中存在的实际连接数(有效的实际连接)
private int _spareRealFormPool;//空闲的实际连接
private int _useRealFormPool;//已分配的实际连接
private int _readOnlyFormPool;//连接池已经分配多少只读连接
private int _useFormPool;//已经分配出去的连接数
private int _spareFormPool;//目前可以提供的连接数
private int _maxConnection;//最大连接数,最大可以创建的连接数目
private int _minConnection;//最小连接数
private int _seepConnection;//每次创建连接的连接数
private int _keepRealConnection;//保留的实际空闲连接,以攻可能出现的ReadOnly使用,当空闲连接不足该数值时,连接池将创建seepConnection个连接
private int _exist = 20;//每个连接生存期限 20分钟
private int _maxRepeatDegree = 5;//可以被重复使用次数(引用记数),当连接被重复分配该值所表示的次数时,该连接将不能被分配出去
//当连接池的连接被分配尽时,连接池会在已经分配出去的连接中,重复分配连接(引用记数)。来缓解连接池压力
private DateTime _startTime;//服务启动时间
private string _connString = null;//连接字符串
private ConnTypeEnum _connType;//连接池连接类型
private PoolState _ps;//连接池状态
//内部对象
private List al_All = new List();//实际连接
private Hashtable hs_UseConn = new Hashtable();//正在使用的连接
private System.Timers.Timer time;//监视器记时器
private Thread threadCreate;//创建线程
private bool isThreadCheckRun = false;
//private Mutex mUnique = new Mutex();
#endregion
//--------------------------------------------------------------------
#region 构造方法 与 初始化函数
///
/// 初始化连接池
///
/// 数据库连接字符串
public Pool(string connectionString)
{ InitConnectionPool(connectionString, ConnTypeEnum.Odbc, 200, 30, 10, 5, 5); }
///
/// 初始化连接池
///
/// 数据库连接字符串
/// 数据库连接类型
public Pool(string connectionString, ConnTypeEnum cte)
{ InitConnectionPool(connectionString, cte, 200, 30, 10, 5, 5); }
///
/// 初始化连接池
///
/// 数据库连接字符串
/// 数据库连接类型
/// 最大连接数,最大可以创建的连接数目
/// 最小连接数
public Pool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection)
{ InitConnectionPool(connectionString, cte, maxConnection, minConnection, 10, 5, 5); }
///
/// 初始化连接池
///
/// 数据库连接字符串
/// 数据库连接类型
/// 最大连接数,最大可以创建的连接数目
/// 最小连接数
/// 每次创建连接的连接数
/// 保留连接数,当空闲连接不足该数值时,连接池将创建seepConnection个连接
public Pool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConnection, int keepConnection)
{ InitConnectionPool(connectionString, cte, maxConnection, minConnection, seepConnection, keepConnection, 5); }
///
/// 初始化连接池
///
/// 数据库连接字符串
/// 数据库连接类型
/// 最大连接数,最大可以创建的连接数目
/// 最小连接数
/// 每次创建连接的连接数
/// 保留连接数,当空闲连接不足该数值时,连接池将创建seepConnection个连接
/// 当空闲的实际连接不足该值时创建连接,直到达到最大连接数
public Pool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConnection, int keepConnection, int keepRealConnection)
{ InitConnectionPool(connectionString, cte, maxConnection, minConnection, seepConnection, keepConnection, keepRealConnection); }
///
/// 初始化函数
///
protected void InitConnectionPool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConnection, int keepConnection, int keepRealConnection)
{
if (cte == ConnTypeEnum.None)
throw new ConnTypeExecption();//参数不能是None
_ps = PoolState.UnInitialize;
this._connString = connectionString;
this._connType = cte;
this._minConnection = minConnection;
this._seepConnection = seepConnection;
this._keepRealConnection = keepRealConnection;
this._maxConnection = maxConnection;
this.time = new System.Timers.Timer(500);
this.time.Stop();
this.time.Elapsed += new System.Timers.ElapsedEventHandler(time_Elapsed);
this.threadCreate = new Thread(new ThreadStart(createThreadProcess));
}
#endregion
//--------------------------------------------------------------------
#region 属性部分
///
/// 连接池服务状态
///
public PoolState State
{ get { return _ps; } }
///
/// 连接池是否启动,改变该属性将相当于调用StartServices或StopServices方法,注:只有连接池处于Run,Stop状态情况下才可以对此属性赋值
///
public bool Enable
{
get
{
if (_ps == PoolState.Run)
return true;
else
return false;
}
set
{
if (_ps == PoolState.Run || _ps == PoolState.Stop)
if (value == true)
StartServices();
else
StopServices();
else
throw new SetValueExecption();//只有连接池处于Run,Stop状态情况下才可以对此属性赋值
}
}
///
/// 得到或设置连接类型
///
public ConnTypeEnum ConnectionType
{
get { return _connType; }
set
{
if (_ps == PoolState.Stop)
_connType = value;
else
throw new SetValueExecption();//只有在Stop状态时才可操作
}
}
///
/// 连接池使用的连接字符串
///
public string ConnectionString
{
get { return _connString; }
set
{
if (_ps == PoolState.Stop)
_connString = value;
else
throw new SetValueExecption();//只有在Stop状态时才可操作
}
}
///
/// 得到服务器运行时间
///
public DateTime RunTime
{
get
{
if (_ps == PoolState.Stop)
return new DateTime(DateTime.Now.Ticks - _startTime.Ticks);
else
return new DateTime(0);
}
}
///
/// 最小连接数
///
public int MinConnection
{
get { return _minConnection; }
set
{
if (value < _maxConnection && value > 0 && value >= _keepRealConnection)
_minConnection = value;
else
throw new ParameterBoundExecption();//参数范围应该在 0~MaxConnection之间,并且应该大于KeepConnection
}
}
///
/// 最大连接数,最大可以创建的连接数目
///
public int MaxConnection
{
get { return _maxConnection; }
set
{
if (value >= _minConnection && value > 0)
_maxConnection = value;
else
throw new ParameterBoundExecption();//参数范围错误,参数应该大于minConnection
}
}
///
/// 每次创建连接的连接数
///
public int SeepConnection
{
get { return _seepConnection; }
set
{
if (value > 0 && value < _maxConnection)
_seepConnection = value;
else
throw new ParameterBoundExecption();//创建连接的步长应大于0,同时小于MaxConnection
}
}
///
/// 保留的实际空闲连接,以攻可能出现的ReadOnly使用
///
public int KeepRealConnection
{
get { return _keepRealConnection; }
set
{
if (value >= 0 && value < _maxConnection)
_keepRealConnection = value;
else
throw new ParameterBoundExecption();//保留连接数应大于等于0,同时小于MaxConnection
}
}
///
/// 自动清理连接池的时间间隔
///
public double Interval
{
get { return time.Interval; }
set { time.Interval = value; }
}
///
/// 每个连接生存期限(单位分钟),默认20分钟
///
public int Exist
{
get { return _exist; }
set
{
if (_ps == PoolState.Stop)
_exist = value;
else
throw new PoolNotStopException();//只有在Stop状态下才可以操作
}
}
///
/// 可以被重复使用次数(引用记数)当连接被重复分配该值所表示的次数时,该连接将不能被分配出去。
/// 当连接池的连接被分配尽时,连接池会在已经分配出去的连接中,重复分配连接(引用记数)。来缓解连接池压力
///
public int MaxRepeatDegree
{
get { return _maxRepeatDegree; }
set
{
if (value >= 0)
_maxRepeatDegree = value;
else
throw new ParameterBoundExecption();//重复引用次数应大于等于0
}
}
///
/// 连接池最多可以提供多少个连接
///
public int MaxConnectionFormPool
{ get { return _maxConnection * _maxRepeatDegree; } }
///
/// 连接池中存在的实际连接数(有效的实际连接)
///
public int PotentRealFormPool
{
get
{
if (_ps == PoolState.Run)
return _potentRealFormPool;
else
throw new PoolNotRunException();//连接池处在非运行中
}
}
///
/// 连接池中存在的实际连接数(包含失效的连接)
///
public int RealFormPool
{
get
{
if (_ps == PoolState.Run)
return _realFormPool;
else
throw new PoolNotRunException();//连接池处在非运行中
}
}
///
/// 空闲的实际连接
///
public int SpareRealFormPool
{
get
{
if (_ps == PoolState.Run)
return _spareRealFormPool;
else
throw new PoolNotRunException();//连接池处在非运行中
}
}
///
/// 已分配的实际连接
///
public int UseRealFormPool
{
get
{
if (_ps == PoolState.Run)
return _useRealFormPool;
else
throw new PoolNotRunException();//连接池处在非运行中
}
}
///
/// 连接池已经分配多少只读连接
///
public int ReadOnlyFormPool
{
get
{
if (_ps == PoolState.Run)
return _readOnlyFormPool;
else
throw new PoolNotRunException();//连接池处在非运行中
}
}
///
/// 已经分配的连接数
///
public int UseFormPool
{
get
{
if (_ps == PoolState.Run)
return _useFormPool;
else
throw new PoolNotRunException();//连接池处在非运行中
}
}
///
/// 目前可以提供的连接数
///
public int SpareFormPool
{
get
{
if (_ps == PoolState.Run)
return _spareFormPool;
else
throw new PoolNotRunException();//连接池处在非运行中
}
}
#endregion
//--------------------------------------------------------------------
#region 启动服务 与 终止服务
///
/// 启动服务,线程安全,同步调用
///
public void StartServices()
{ StartServices(false); }
///
/// 启动服务,线程安全
///
/// 是否异步调用True为是,异步调用指,用户调用该方法后,无须等待创建结束就可继续做其他操作
public void StartServices(bool ansy)
{
lock (this)
{
createThreadMode = 0;//工作模式0
createThreadProcessRun = true;
createThreadProcessTemp = _minConnection;
if (_ps == PoolState.UnInitialize)
threadCreate.Start();
else if (_ps == PoolState.Stop)
threadCreate.Interrupt();
else
throw new PoolNotStopException();//服务已经运行或者未完全结束
time.Start();
}
if (!ansy)
while (threadCreate.ThreadState != ThreadState.WaitSleepJoin) { Thread.Sleep(50); }//等待可能存在的创建线程结束
}
///
/// 停止服务,线程安全
///
public void StopServices()
{ StopServices(false); }
///
/// 停止服务,线程安全
/// 是否必须退出;如果指定为false与StartServices()功能相同,如果指定为true。将未收回的连接资源关闭,这将是危险的。认为可能你的程序正在使用此资源。
///
public void StopServices(bool needs)
{
lock (this)
{
if (_ps == PoolState.Run)
{
lock (hs_UseConn)
{
if (needs == true)//必须退出
hs_UseConn.Clear();
else
if (hs_UseConn.Count != 0)
throw new ResCallBackException();//连接池资源未全部回收
}
time.Stop();
while (isThreadCheckRun) { Thread.Sleep(50); }//等待timer事件结束
createThreadProcessRun = false;
while (threadCreate.ThreadState != ThreadState.WaitSleepJoin) { Thread.Sleep(50); }//等待可能存在的创建线程结束
lock (al_All)
{
for (int i = 0; i < al_All.Count; i++)
al_All[i].Dispose();
al_All.Clear();
}
_ps = PoolState.Stop;
}
else
throw new PoolNotRunException();//服务未启动
}
UpdateAttribute();//更新属性
}
public void Dispose()
{
try
{
this.StopServices();
threadCreate.Abort();
}
catch (Exception e) { }
}
#endregion
//--------------------------------------------------------------------
#region 获得连接 与 释放连接
///
/// 在连接池中申请一个连接,使用None级别,线程安全
///
/// 发起者
/// 返回申请到的连接
public DbConnection GetConnectionFormPool(object key)
{ return GetConnectionFormPool(key, ConnLevel.None); }
///
/// 在连接池中申请一个连接,线程安全
///
/// 申请者
/// 申请的连接级别
/// 返回申请到的连接
public DbConnection GetConnectionFormPool(object key, ConnLevel cl)
{
lock (this)
{
if (_ps != PoolState.Run)
throw new StateException();//服务状态错误
if (hs_UseConn.Count == MaxConnectionFormPool)
throw new PoolFullException();//连接池已经饱和,不能提供连接
if (hs_UseConn.ContainsKey(key))
throw new KeyExecption();//一个key对象只能申请一个连接
if (cl == ConnLevel.ReadOnly)
return GetConnectionFormPool_ReadOnly(key);//ReadOnly级别
else if (cl == ConnLevel.High)
return GetConnectionFormPool_High(key);//High级别
else if (cl == ConnLevel.None)
return GetConnectionFormPool_None(key);//None级别
else
return GetConnectionFormPool_Bottom(key);//Bottom级别
}
}
///
/// 申请一个连接资源,只读方式,线程安全
///
/// 申请者
/// 申请到的连接对象
protected DbConnection GetConnectionFormPool_ReadOnly(object key)
{
ConnStruct cs = null;
for (int i = 0; i < al_All.Count; i++)
{
cs = al_All[i];
if (cs.Enable == false || cs.Allot == false || cs.UseDegree == _maxRepeatDegree || cs.IsUse == true)
continue;
return GetConnectionFormPool_Return(key, cs, ConnLevel.ReadOnly); //返回得到的连接
}
return GetConnectionFormPool_Return(key, null, ConnLevel.ReadOnly);
}
///
/// 申请一个连接资源,优先级-高,线程安全
///
/// 申请者
/// 申请到的连接对象
protected DbConnection GetConnectionFormPool_High(object key)
{
ConnStruct cs = null;
ConnStruct csTemp = null;
for (int i = 0; i < al_All.Count; i++)
{
csTemp = al_All[i];
if (csTemp.Enable == false || csTemp.Allot == false || csTemp.UseDegree == _maxRepeatDegree)//不可以分配跳出本次循环。
{
csTemp = null;
continue;
}
if (csTemp.UseDegree == 0)//得到最合适的
{
cs = csTemp;
break;
}
else//不是最合适的放置到最佳选择中
{
if (cs != null)
{
if (csTemp.UseDegree < cs.UseDegree)
//与上一个最佳选择选出一个最佳的放置到cs中
cs = csTemp;
}
else
cs = csTemp;
}
}
return GetConnectionFormPool_Return(key, cs, ConnLevel.High);//返回最合适的连接
}
///
/// 申请一个连接资源,优先级-中,线程安全
///
/// 申请者
/// 申请到的连接对象
protected DbConnection GetConnectionFormPool_None(object key)
{
List al = new List();
ConnStruct cs = null;
for (int i = 0; i < al_All.Count; i++)
{
cs = al_All[i];
if (cs.Enable == false || cs.Allot == false || cs.UseDegree == _maxRepeatDegree)//不可以分配跳出本次循环。
continue;
if (cs.Allot == true)
al.Add(cs);
}
if (al.Count == 0)
return GetConnectionFormPool_Return(key, null, ConnLevel.None);//发出异常
else
return GetConnectionFormPool_Return(key, (al[al.Count / 2]), ConnLevel.None);//返回连接
}
///
/// 申请一个连接资源,优先级-低,线程安全
///
/// 申请者
/// 申请到的连接对象
protected DbConnection GetConnectionFormPool_Bottom(object key)
{
ConnStruct cs = null;
ConnStruct csTemp = null;
for (int i = 0; i < al_All.Count; i++)
{
csTemp = al_All[i];
if (csTemp.Enable == false || csTemp.Allot == false || csTemp.UseDegree == _maxRepeatDegree)//不可以分配跳出本次循环。
{
csTemp = null;
continue;
}
else//不是最合适的放置到最佳选择中
{
if (cs != null)
{
if (csTemp.UseDegree > cs.UseDegree)
//与上一个最佳选择选出一个最佳的放置到cs中
cs = csTemp;
}
else
cs = csTemp;
}
}
return GetConnectionFormPool_Return(key, cs, ConnLevel.Bottom);//返回最合适的连接
}
///
/// 返回DbConnection对象,同时做获得连接时的必要操作
///
/// key
/// ConnStruct对象
/// 级别
/// 是否为只读属性
///
private DbConnection GetConnectionFormPool_Return(object key, ConnStruct cs, ConnLevel cl)
{
try
{
if (cs == null)
throw new Exception();
cs.Repeat();
hs_UseConn.Add(key, cs);
if (cl == ConnLevel.ReadOnly)
{
cs.Allot = false;
cs.IsRepeat = false;
}
}
catch (Exception e)
{
throw new OccasionExecption();//连接资源耗尽,或错误的访问时机。
}
finally
{
UpdateAttribute();//更新属性
}
return cs.Connection;
}
///
/// 释放申请的数据库连接对象,线程安全
/// key表示数据库连接申请者
///
public void DisposeConnection(object key)
{
lock (hs_UseConn)
{
ConnStruct cs = null;
if (_ps == PoolState.Run)
{
if (!hs_UseConn.ContainsKey(key))
throw new NotKeyExecption();//无法释放,不存在的key
cs = (ConnStruct)hs_UseConn[key];
cs.IsRepeat = true;
if (cs.Allot == false)
if (cs.Enable == true)
cs.Allot = true;
cs.Remove();
hs_UseConn.Remove(key);
}
else
throw new PoolNotRunException();//服务未启动
}
UpdateAttribute();//更新属性
}
#endregion
//--------------------------------------------------------------------
#region 私有方法
private int createThreadMode = 0;//创建线程工作模式
private int createThreadProcessTemp = 0;//需要创建的连接数
private bool createThreadProcessRun = false;//是否决定创建线程将继续工作,如果不继续工作则线程会将自己处于阻止状态
///
/// 创建线程
///
private void createThreadProcess()
{
bool join = false;
int createThreadProcessTemp_inside = createThreadProcessTemp;
_ps = PoolState.Initialize;
while (true)
{
join = false;
_ps = PoolState.Run;
if (createThreadProcessRun == false)
{//遇到终止命令
try { threadCreate.Join(); }
catch (Exception e) { }
}
else
{
if (createThreadMode == 0)
{
//------------------------begin mode 创建模式
lock (al_All)
{
if (al_All.Count < createThreadProcessTemp_inside)
al_All.Add(CreateConnection(_connString, _connType));
else
join = true;
}
//------------------------end mode
}
else if (createThreadMode == 1)
{
//------------------------begin mode 增加模式
lock (al_All)
{
if (createThreadProcessTemp_inside != 0)
{
createThreadProcessTemp_inside--;
al_All.Add(CreateConnection(_connString, _connType));
}
else
join = true;
}
//------------------------end mode
}
else
join = true;
//-------------------------------------------------------------------------
if (join == true)
{
UpdateAttribute();//更新属性
try
{
createThreadProcessTemp = 0;
threadCreate.Join();
}
catch (Exception e)
{ createThreadProcessTemp_inside = createThreadProcessTemp; }//得到传入的变量
}
}
}
}
///
/// 检测事件
///
private void time_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
ConnStruct cs = null;
time.Stop();//关闭自己
isThreadCheckRun = true;
//如果正在执行创建连接则退出
if (threadCreate.ThreadState != ThreadState.WaitSleepJoin)
return;
//------------------------------------------------------
lock (al_All)
{
int n = 0;
for (int i = 0; i < al_All.Count; i++)
{
cs = al_All[i];
TestConnStruct(cs);//测试
if (cs.Enable == false && cs.RepeatNow == 0)//没有引用的失效连接
{
cs.Close();//关闭它
al_All.Remove(cs);//删除
}
}
}
//------------------------------------------------------
UpdateAttribute();//更新属性
if (_spareRealFormPool < _keepRealConnection)//保留空闲实际连接数不足
createThreadProcessTemp = GetNumOf(_realFormPool, _seepConnection, _maxConnection);
else
createThreadProcessTemp = 0;
//if (createThreadProcessTemp != 0)
// Console.WriteLine("创建" + createThreadProcessTemp);
if (createThreadProcessTemp != 0)
{
//启动创建线程,工作模式1
createThreadMode = 1;
threadCreate.Interrupt();
}
isThreadCheckRun = false;
time.Start();//打开自己
}
///
/// 得到当前要增加的量
///
private int GetNumOf(int nowNum, int seepNum, int maxNum)
{
if (maxNum >= nowNum + seepNum)
return seepNum;
else
return maxNum - nowNum;
}
///
/// 用指定类型创建连接
///
/// 连接字符串
/// 连接类型
/// 连接超时时间
/// 返回创建的连接
private ConnStruct CreateConnection(string conn, ConnTypeEnum cte)
{
DbConnection db = null;
if (cte == ConnTypeEnum.Odbc)
db = new System.Data.Odbc.OdbcConnection(conn);//ODBC数据源连接
else if (cte == ConnTypeEnum.OleDb)
db = new System.Data.OleDb.OleDbConnection(conn);//OLE DB数据连接
else if (cte == ConnTypeEnum.SqlClient)
db = new System.Data.SqlClient.SqlConnection(conn);//SqlServer数据库连接
ConnStruct cs = new ConnStruct(db, cte, DateTime.Now);
cs.Open();
return cs;
}
///
/// 测试ConnStruct是否过期
///
/// 被测试的ConnStruct
private void TestConnStruct(ConnStruct cs)
{
//此次被分配出去的连接是否在此次之后失效
if (cs.UseDegree == _maxRepeatDegree)
cs.SetConnectionLost();//超过使用次数
if (cs.CreateTime.AddMinutes(_exist).Ticks <= DateTime.Now.Ticks)
cs.SetConnectionLost();//连接超时
if (cs.Connection.State == ConnectionState.Closed)
cs.SetConnectionLost();//连接被关闭
}
///
/// 更新属性
///
private void UpdateAttribute()
{
int temp_readOnlyFormPool = 0;//连接池已经分配多少只读连接
int temp_potentRealFormPool = 0;//连接池中存在的实际连接数(有效的实际连接)
int temp_spareRealFormPool = 0;//空闲的实际连接
int temp_useRealFormPool = 0;//已分配的实际连接
int temp_spareFormPool = MaxConnectionFormPool;//目前可以提供的连接数
//---------------------------------
lock (hs_UseConn)
{
_useFormPool = hs_UseConn.Count;
}
//---------------------------------
ConnStruct cs = null;
int n = 0;
lock (al_All)
{
_realFormPool = al_All.Count;
for (int i = 0; i < al_All.Count; i++)
{
cs = al_All[i];
//只读
if (cs.Allot == false && cs.IsUse == true && cs.IsRepeat == false)
temp_readOnlyFormPool++;
//有效的实际连接
if (cs.Enable == true)
temp_potentRealFormPool++;
//空闲的实际连接
if (cs.Enable == true && cs.IsUse == false)
temp_spareRealFormPool++;
//已分配的实际连接
if (cs.IsUse == true)
temp_useRealFormPool++;
//目前可以提供的连接数
if (cs.Allot == true)
temp_spareFormPool = temp_spareFormPool - cs.RepeatNow;
else
temp_spareFormPool = temp_spareFormPool - _maxRepeatDegree;
}
}
_readOnlyFormPool = temp_readOnlyFormPool;
_potentRealFormPool = temp_potentRealFormPool;
_spareRealFormPool = temp_spareRealFormPool;
_useRealFormPool = temp_useRealFormPool;
_spareFormPool = temp_spareFormPool;
}
#endregion
}
}