首先说明一下:这个例子是来源于【C#线程参考手册】参考手册内的一个例子,在这个我只是想研究一下她的设计原理。
具体好用不好用,因为没有做具体项目的测试,所以提醒大家注意。
1 设计思路:
1.1 在程序的全局利用单例模式建立一个数据库连接池对象。
1.2 获得数据库连接方法BorrowDBConnection()。
这个方法的作用如下:
如果【待清理的池】内DB连接对象不是关闭状态,则添加到【DB连接池】,继续使用。
如果【待清理的池】内DB连接对象是关闭状态,则DB连接被移除【待清理的池】,之后被关闭。
如果【待清理的池】不存在DB连接对象,则创建DB连接对象后,附加到【DB连接池】内,然后使用她。
1.3 返回数据库连接给【待清理的池】,方法是ReturnObjectToPool()。
【DB连接池】删除DB连接对象。
【待清理的池】追加DB连接对象。
1.4 延迟DB连接对象的垃圾回收事件
通过Timer的Elapsed事件,来实现【待清理的池】内的DB连接对象的关闭处理。
2 UML图例:
这里要说明的是,为什么要继承ObjectPool类呢?
因为ObjectPool类的结构对于所有使用池、可手动释放资源的对象是通用的。
3 具体代码如下:
3.1 ObjectPool类(真的很通用的一个类,设计的很好,感觉可以继承她做任何事)
- using System;
- using System.Collections;
- using System.Timers;
- using System.Text;
- namespace SqlPool
- {
- public abstract class ObjectPool
- {
- /// <summary>
- /// //当前日期时间刻度值,用户判断连接是否超时
- /// </summary>
- private long _lastCheckOut;
- /// <summary>
- /// 使用对象池
- /// </summary>
- private static Hashtable locked;
- /// <summary>
- /// 清理对象池
- /// </summary>
- private static Hashtable unlocked;
- internal static long GARBAGE_INTERVAL = 5 * 1000;
- /// <summary>
- /// 构造函数1,说明了两个池是同步的。
- /// </summary>
- static ObjectPool()
- {
- locked = Hashtable.Synchronized(new Hashtable());
- unlocked = Hashtable.Synchronized(new Hashtable());
- }
- /// <summary>
- /// 初始化时间间隔,时间间隔触发事件,释放清理对象池的对象
- /// </summary>
- internal ObjectPool()
- {
- _lastCheckOut = DateTime.Now.Ticks;
- System.Timers.Timer aTimer = new System.Timers.Timer();
- aTimer.Enabled = true;
- aTimer.Interval = GARBAGE_INTERVAL;
- aTimer.Elapsed += new ElapsedEventHandler(CollectGarbage);
- }
- /// <summary>
- /// 建立一个数据库连接
- /// </summary>
- /// <returns></returns>
- protected abstract object Create();
- /// <summary>
- /// 判断数据库连接是否正常
- /// </summary>
- /// <param name="o"></param>
- /// <returns></returns>
- protected abstract bool Validate(object o);
- /// <summary>
- /// 延迟的连接被关闭
- /// </summary>
- /// <param name="o"></param>
- protected abstract void Expire(object o);
- /// <summary>
- /// Sql连接超出指定时间后的垃圾回收
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="ea"></param>
- private void CollectGarbage(object sender, ElapsedEventArgs ea)
- {
- lock (this)
- {
- object o;
- long now = DateTime.Now.Ticks;
- IDictionaryEnumerator e = unlocked.GetEnumerator();
- try {
- while (e.MoveNext())
- {
- o = e.Key;
- if(now-((long)unlocked[o])>GARBAGE_INTERVAL)
- {
- unlocked.Remove(o);
- Expire(o);
- o = null;
- }
- }
- }
- catch{}
- }
- }
- /// <summary>
- /// 获得数据库连接
- /// </summary>
- /// <returns></returns>
- internal object GetObjectFromPool()
- {
- long now = DateTime.Now.Ticks;
- _lastCheckOut = now;
- object o = null;
- lock (this)
- {
- try
- {
- foreach (DictionaryEntry myEntry in unlocked)
- {
- o = myEntry.Key;
- if (Validate(o))
- {
- unlocked.Remove(o);
- locked.Add(o, now);
- return (o);
- }
- else
- {
- unlocked.Remove(o);
- Expire(o);
- o = null;
- }
- }
- }
- catch (Exception) { }
- o = Create();
- locked.Add(o, now);
- }
- return o;
- }
- /// <summary>
- /// 清除数据库连接
- /// </summary>
- /// <param name="o"></param>
- internal void ReturnObjectToPool(object o)
- {
- if (o != null)
- {
- lock (this)
- {
- locked.Remove(o);
- unlocked.Add(o, DateTime.Now.Ticks);
- }
- }
- }
- }
- }
3.2 DBConnectionSingleton类 - 数据库连接池(实现了ObjectPool类的Create,Validate,Expire方法,并使用了单例模式)
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Data.SqlClient;
- namespace SqlPool
- {
- class DBConnectionSingleton:ObjectPool
- {
- private DBConnectionSingleton() { }
- /// <summary>
- /// 以单例模式创建数据库连接池
- /// </summary>
- public static readonly DBConnectionSingleton Instance = new DBConnectionSingleton();
- private static string _connectionString = @"Data Source=192.168.168.251/Sql2005;Initial Catalog=XX;User ID=sa;Password=777";
- /// <summary>
- /// 数据库连接字符串
- /// </summary>
- public static string ConnectionString
- {
- set {
- _connectionString = value;
- }
- get
- {
- return _connectionString;
- }
- }
- /// <summary>
- /// 创建数据库连接
- /// </summary>
- /// <returns></returns>
- protected override object Create()
- {
- SqlConnection temp = new SqlConnection(_connectionString);
- temp.Open();
- return temp;
- }
- /// <summary>
- /// 判断DB是否已连接
- /// </summary>
- /// <param name="o"></param>
- /// <returns></returns>
- protected override bool Validate(object o)
- {
- try
- {
- SqlConnection temp = (SqlConnection)o;
- return (!((temp.State.Equals(System.Data.ConnectionState.Closed))));
- }
- catch
- {
- return false;
- }
- }
- /// <summary>
- /// 关闭DB连接
- /// </summary>
- /// <param name="o"></param>
- protected override void Expire(object o)
- {
- try
- {
- ((SqlConnection)o).Close();
- }
- catch {
- }
- }
- /// <summary>
- /// 获得DB连接
- /// </summary>
- /// <returns></returns>
- public SqlConnection BorrowDBConnection()
- {
- try
- {
- return ((SqlConnection)base.GetObjectFromPool());
- }
- catch(Exception e) {
- throw e;
- }
- }
- /// <summary>
- /// 清除DB连接
- /// </summary>
- /// <param name="e"></param>
- public void ReturnDBConnecion(SqlConnection e)
- {
- base.ReturnObjectToPool(e);
- }
- }
- }
3.3 Main函数
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Data.SqlClient;
- namespace SqlPool
- {
- class Program
- {
- static void Main(string[] args)
- {
- DBConnectionSingleton pool;
- //获得数据库连接池的单例模式。
- pool = DBConnectionSingleton.Instance;
- DBConnectionSingleton.ConnectionString = @"Data Source=192.168.168.251/Sql2005;Initial Catalog=XX;User ID=sa;Password=777";
- SqlConnection myConnection = pool.BorrowDBConnection();
- pool.ReturnDBConnecion(myConnection);
- System.Threading.Thread.Sleep(5000);
- }
- }
- }