以下是代码片段:
/// <summary> /// Access数据库连接池 /// </summary> internal class AccessPool : IDisposable { /// <summary> /// 连接字符串 /// </summary> private String ConnectionString; /// <summary> /// 私有构造函数,禁止外部创建实例。 /// </summary> /// <param name="connStr">连接字符串</param> private AccessPool(String connStr) { ConnectionString = connStr; }
/// <summary> /// 释放所有连接 /// </summary> public void Dispose() { lock (this) { foreach (OleDbConnection conn in FreeList) { try { conn.Close(); } catch { } } FreeList.Clear(); foreach (OleDbConnection conn in UsedList) { try { conn.Close(); } catch { } } UsedList.Clear(); } }
~AccessPool() { foreach (AccessPool pool in Pools.Values) { pool.Dispose(); } lock (Pools) { Pools.Clear(); } }
/// <summary> /// 空闲列表 /// </summary> private List<OleDbConnection> FreeList = new List<OleDbConnection>(); /// <summary> /// 使用列表 /// </summary> private List<OleDbConnection> UsedList = new List<OleDbConnection>();
/// <summary> /// 取连接 /// </summary> /// <returns></returns> private OleDbConnection GetConnection() { // 多线程冲突锁定,一下代码在同一时刻只能有一个线程进入 lock (this) { if (UsedList.Count >= MaxPoolSize) throw new Exception("连接池的连接数超过最大限制,无法提供服务"); OleDbConnection conn; // 看看是否还有连接,如果没有,需要马上创建 if (FreeList.Count < 1) { conn = new OleDbConnection(ConnectionString); conn.Open(); // 直接进入使用列表 UsedList.Add(conn); return conn; } // 从空闲列表中取第一个连接 conn = FreeList[0]; // 第一个连接离开空闲列表 FreeList.RemoveAt(0); // 该连接进入使用列表 UsedList.Add(conn); // 检查连接是否已经打开,如果没打开,则打开 if (conn.State == ConnectionState.Closed) conn.Open(); return conn; } }
/// <summary> /// 返还连接 /// </summary> /// <param name="conn">连接对象</param> private void ReturnConnection(OleDbConnection conn) { // 检查该连接对象是否来自本连接池 if (!UsedList.Contains(conn)) return; lock (this) { // 离开使用列表 UsedList.Remove(conn); // 回到空闲列表 FreeList.Add(conn); } }
/// <summary> /// 检查连接池。清理一个未使用连接,防止打开过多连接而又不关闭 /// </summary> private void CheckPool() { lock (this) { if (FreeList.Count > 0 && FreeList.Count + UsedList.Count > MinPoolSize) { #if DEBUG Trace.WriteLine("检查清理连接池……"); #endif OleDbConnection conn = FreeList[0]; FreeList.RemoveAt(0); try { conn.Close(); conn.Dispose(); } catch { } } } } /// <summary> /// 最大池大小 /// </summary> public int MaxPoolSize = 10; /// <summary> /// 最小池大小 /// </summary> public int MinPoolSize = 2; /// <summary> /// 连接池集合。连接字符串作为索引,每个连接字符串对应一个连接池。 /// </summary> private static Dictionary<String, AccessPool> Pools = new Dictionary<string, AccessPool>();
/// <summary> /// 获得连接 /// </summary> /// <param name="connStr">连接字符串</param> /// <returns></returns> public static OleDbConnection GetConnection(String connStr) { // 检查是否存在连接字符串为connStr的连接池 if (!Pools.ContainsKey(connStr)) { lock (Pools) { if (!Pools.ContainsKey(connStr)) Pools.Add(connStr, new AccessPool(connStr)); } } // 从现在开始10秒后,每隔10秒检查一次连接池,删除一个不使用的连接 if (timer == null) timer = new Timer(new TimerCallback(CheckPool), null, 10000, 10000); return Pools[connStr].GetConnection(); }
/// <summary> /// 把连接返回连接池 /// </summary> /// <param name="connStr">连接字符串</param> /// <param name="conn">连接</param> public static void ReturnConnection(String connStr, OleDbConnection conn) { if (!Pools.ContainsKey(connStr)) return; Pools[connStr].ReturnConnection(conn); }
private static Timer timer; /// <summary> /// 定时检查连接池,每次检查都删除每个连接池的一个空闲连接 /// </summary> /// <param name="obj"></param> private static void CheckPool(Object obj) { foreach (AccessPool pool in Pools.Values) { pool.CheckPool(); } } } |