首页 新生命讲座 ASP学习 Net编程 我的垃圾工具 我的宝贝 系统编程
编译原理 其它文章
 -> 首页 -> Net编程
OLEDB连接池
作者:大石头   来源:   发布时间:2007-2-16 3:37:26   共有284位读者阅读过此文


近来比较忙,没来得及认真研究ADO.Net中的OLEDB是否已经带有连接池,我经过测试发现,每次操作都打开然后关闭连接,比只打开一次要慢很多,于是做了这个东西。记得早两周 狂图 还问我有没有OLEDB连接池呢。

代码注释很多,就不多说了。

以下是代码片段:

 /// <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();
   }
  }
 }


评论
狂图 2007-2-25 10:16:32
无法从密封类型System.Data.OleDb.OleDbConnection派生

狂图 2007-2-25 10:13:53
我也希望OleDbConnection能被继承

大石头 2007-2-25 1:07:53
你可以再写一个类,继承自OleDbConnection的,重写Open方法,剩下的,你应该能明白我的意思了吧,呵呵,非常简单。

狂图 2007-2-21 22:52:28
你好,你说的代码,我看到了。不过说实话,不能解决我的问题啊。 如果把我自己的系统重新写一遍全用你这个类倒可以,但是我的代码是写好了的。如下,就是我的代码格式 //开始事务 //DbFactory.CreateConnection()是根据系统的配置来产生一个具体的DbConnection using (DbConnection conn = DbFactory.CreateConnection()) { conn.Open(); DbTransaction trans = conn.BeginTransaction(); try { //TODO具体的事务操作 // 提交事务 trans.Commit(); } catch (Exception e) { try { trans.Rollback(); } catch { } throw new Exception("文章处理出错!",e); } 如上的代码,使用SqlConnection的时候是没有问题的,SqlConnection支持连接池,使用Oledb的时候就不能支持连接池了,所以需要一个继承自DbConnection的,实现IDispose的数据连接类。

发表评论
网名:
评论:
    
新生命 CMS1.0 Build0920 版权所有 All Copyrights @2006 桂ICP备06011573号
站长:大石头 信箱:gxuhy@21cn.com QQ:99363590