数据库连接池类

// Writen by 咏南工作室(陈新光) 2009-6-26 11:58:17
// 数据库连接池类
// 使用ADO引擎,支持access, sqlServer, oracle三种数据库
// 连接对象.tag = 正数 表示此连接对象处于非使用状态,否则反之
// 所有时间单位均为秒

unit UDataConnPool;
{$HINTS OFF}
{$WARNINGS OFF}
interface

uses
  SysUtils, Classes, DB, ADODB, Contnrs, Windows, ExtCtrls;

// 常量定义
const
  c_sql = 'sqloledb';
  c_access = 'microsoft.jet.oledb.4.0';
  c_oracle = 'MSDAORA.1';

// 自定义数据类型
type
  TDBType=(Access, SqlServer, Oracle);    // 可支持的数据库类型

  RConnParameter = record                 // 连接池的参数结构体
    ConnMin: Integer;                     // 连接池最小要保留的连接对象数量
    ConnMax: Integer;                     // 连接池最大可拥有的连接对象数量
    TimeOut: Integer;                     // 非使用中连接对象的超时时间
    TimeOut2: Integer;                    // 使用中连接对象的超时时间
    RefreshTime: Integer;                 // 定时轮询连接池的时间 
    dbSource: string;                     // data source
    DB: string;                           // sql server 特有 Initial Catalog
    dbUser: string;                       // user id 
    dbPass: string;                       // password
    dbpass2: string;                      // access 特有 Database Password
  end;

  TDataConnectionPool = class(TComponent) // 数据库连接池类
  private
    fConnParameter: RConnParameter;                  // 连接池参数
    fConnList: TComponentList;                       // 连接池容器
    fCleanTimer: TTimer;                             // 定时轮询连接池
    fDBType: TDBType;                                // 数据库类型
    procedure fCleanOnTime(sender: TObject);         // 定时轮询连接池
    function fCreateADOConn: TADOConnection;         // 创建连接对象
    procedure fClean;                                // 处理轮询连接池动作
    { Private declarations }
  protected
    function getConnCount: Integer;                  // 获取连接池内的连接对象的总数
  public
    { Public declarations }
    property ConnCount: Integer read getConnCount;   // 连接池内的连接对象的总数
    constructor Create(owner: TComponent; connParam: RConnParameter; dbType: TDBType);  // 创建者方法
    // owner -- 拥有者
    // connParam -- 连接池的参数
    // dbType -- 支持的数据库类型
    function getConn: TADOConnection;                // 从连接池内获取非使用中的连接对象
    procedure returnConn(conn: TADOConnection);      // 使用完的连接对象归还连接池内 
end;

implementation

constructor TDataConnectionPool.Create(owner: TComponent; connParam: RConnParameter; dbType: TDBType);
// owner -- 拥有者
// connParam -- 连接池的参数
// dbType -- 支持的数据库类型
var
  index: Integer;
begin
  inherited Create(owner);
  fDBType := dbType;
  fConnParameter := connParam;

  if fConnList = nil then
  begin
    fConnList := TComponentList.Create;            // 创建连接池容器
    for index := 1 to fConnParameter.ConnMin do    // 创建连接对象
      fConnList.Add(fCreateADOConn);
  end;

  if fCleanTimer = nil then                        // 定时轮询连接池
  begin
    fCleanTimer := TTimer.Create(Self);
    fCleanTimer.Name := 'MyCleanTimer1';
    fCleanTimer.Interval := fConnParameter.RefreshTime * 1000;
    fCleanTimer.OnTimer := fCleanOnTime;
    fCleanTimer.Enabled := True;
  end;
end;

procedure TDataConnectionPool.fClean;
var
  iNow: Integer;
  index: Integer;
begin
  iNow := GetTickCount;                                     // 获取当前时间
  for index := fConnList.Count - 1 downto 0 do              // 遍历连接池
  begin
    if TADOConnection(fConnList[index]).Tag > 0 then        // 非使用中的连接
    begin
      if fConnList.Count > fConnParameter.ConnMin then      // 连接池内连接总数 > 最小保留连接数量
      begin
        if iNow - TADOConnection(fConnList[index]).Tag > fConnParameter.TimeOut * 1000 then // 超时
          fConnList.Delete(index);                          // 从连接池内释放此连接对象
      end;
    end
    else if TADOConnection(fConnList[index]).Tag < 0 then   // 使用中的连接
    begin
      if iNow + TADOConnection(fConnList[index]).Tag > fConnParameter.TimeOut2 * 1000 then  // 超时
      begin
        fConnList.Delete(index);                            // 从连接池内释放此连接对象
        if fConnList.Count < fConnParameter.ConnMin then    // 连接池内连接对象 < 最小保留数量
          fConnList.Add(fCreateADOConn);                    // 创建新的连接对象
      end;
    end
  end;
end;

procedure TDataConnectionPool.fCleanOnTime(sender: TObject);
begin
  fClean;
end;

function TDataConnectionPool.fCreateADOConn: TADOConnection;
var
  conn: TADOConnection;
begin
  Conn := TADOConnection.Create(Self);
  with conn do
  begin
    LoginPrompt := False;
    Tag := GetTickCount;

    case fDBType of
      sqlserver:
      begin
        Provider := c_sql;     // 连接SQL SERVER
        Properties['Data Source'].Value := fConnParameter.dbSource;
        Properties['User ID'].Value := fConnParameter.dbUser;
        Properties['Password'].Value := fConnParameter.dbPass;
        Properties['Initial Catalog'].Value := fConnParameter.DB;
      end;

      access:
      begin
        Provider := c_access;   // 连接ACCESS
        Properties['Jet OLEDB:Database Password'].Value := fConnParameter.dbPass2;
        Properties['Data Source'].Value := fConnParameter.dbSource;
        Properties['User ID'].Value := fConnParameter.dbUser;
        Properties['Password'].Value := fConnParameter.dbPass;
      end;

      oracle:                   // 连接ORACLE 
      begin
        Provider:=c_oracle;
        Properties['Data Source'].Value := fConnParameter.dbSource;
        Properties['User ID'].Value := fConnParameter.dbUser;
        Properties['Password'].Value := fConnParameter.dbPass;
      end;
    end;

    try                                     // 尝试连接数据库
      Connected := True;
      Result := conn;
    except
      Result := nil;
      raise Exception.Create('Connect database fail.');
    end;
  end;
end;

function TDataConnectionPool.getConn: TADOConnection;// 从连接池内取没有被使用的连接对象
var
  index: Integer;
begin
  Result := nil;
  for index := 0 to fConnList.Count - 1 do           // 遍历连接池
  begin
    if TADOConnection(fConnList[index]).Tag > 0 then // 非使用的连接对象
    begin
      Result := TADOConnection(fConnList[index]);
      Result.Tag := - GetTickCount;                  // 标记该连接为使用状态
      Break;                                         // 找到后中止循环
    end;
  end;

  if (Result = nil) and (index < fConnParameter.ConnMax) then  // 如果连接池内已经没有可用的连接对象(全部被使用)
  begin
    Result := fCreateADOConn;                                  // 在不超过最大连接对象的基础上创建新的连接对象
    Result.Tag := - GetTickCount;                              // 标记为已使用
    fConnList.Add(Result);                                     // 放入连接池内
  end;
end;

function TDataConnectionPool.getConnCount: Integer;
begin
  Result := fConnList.Count;            // 返回当前连接池内总的连接对象数量
end;

procedure TDataConnectionPool.returnConn(conn: TADOConnection);
begin
  if fConnList.IndexOf(conn) > -1 then  // 判断连接池内是否存在此连接对象
    conn.Tag := GetTickCount;           // 标记此连接对象为可用状态
end;

end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi TThread中文注释2009-10-22 16:58TThread是一个抽象,可以创建几个独立的线程。 关系 TObject 在一个多线程的应用程序中创建一个TThread的后子代表一个线程。每一新子的TThread对象的实例是一个新的线程。从TThread派生的多线程实例可以构成Delphi的多线程应用程序。    当一个应用程序运行时,应用程序就被载入内存准备执行。此时,它成为包含一个或多个线程的进程,每个线程含有数据、代码和系统资源。线程执行应用程序的部分内容,并由系统分配CPU时间。同一进程的所有线程共享同一地址空间,可以访问进程的全局变量。线程通过以下工作改善应用的性能:管理多通信设备的输入。    区分任务的优先级。优先级高的处理紧急的任务。优先级低的处理其他任务。    以下是使用线程的一些建议:    同时跟踪太多的线程消耗CPU时间。对单处理器系统,一个进程最多有16个线程。    当多个线程更新相同的资源时,应使线程同步以避免冲突。    大多数访问VCL对象和更新窗体的方法必须从主VCL线程内部调用。    以下为创建和使用一个新线程的过程:    (1)单击File|New|Thread菜单项,创建一个包含对象的新单元,该对象源于TThread。    (2)定义新线程对象和Create方法。    (3)通过插入线程执行时需要的代码定义线程对象和Execute方法。    (4)将使用VCL组件的任何调用传递给Synchronize方法,以避免多线程冲突。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值