数据库连接池类

// 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.

相关文章