adoQuery对象池

// Writen by 咏南工作室(陈新光) 2009-6-26 14:31:26

{   for example:
var
  q: TADOQuery;
begin
  Result := nil;
  q := g_adoquerypool.GetAdoQuery;
  if q <> nil then
  begin
    q.Close;
    q.SQL.Clear;
    q.SQL.Text := sqlCommand;
    q.Open;
    Result := q;
    g_adoquerypool.returnAdoQuery(q);
  end;
}

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

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

type
  TAdoQueryPool = class(TComponent)    // adoQuery对象池类
  private
    fAdoQueryMin: Integer;             // 对象池最小保留adoQuery数量
    fAdoQueryMax: Integer;             // 对象池最大可拥有adoQuery数量
    fRefreshTime: Integer;             // 定时轮询对象池的时间
    fTimeOut: Integer;                 // 非使用中对象超时时间
    fTimeOut2: Integer;                // 使用中对象超时时间
    fAdoQueryList: TComponentList;     // 对象容器
    fCleanTimer: TTimer;

    procedure fCleanOnTime(sender: TObject);  // 定时轮询对象池方法
    function fCreateADOQuery: TADOQuery;
    procedure fClean;
    function GetPoolSize:Integer;
    { Private declarations }
  public
    { Public declarations }
    constructor Create;
    destructor Destroy; override;
    function GetAdoQuery: TADOQuery;                                  // 获取对象池内非使用中对象
    procedure returnAdoQuery(qry: TADOQuery);                         // 使用完的对象归还对象池内

    property PoolSize: Integer read GetPoolSize;
    property PoolMin: Integer read fAdoQueryMin;
    property PoolMax: Integer read fAdoQueryMax;
    property PoolForTime: Integer read fRefreshTime;
    property PoolNoUseObjTimeOut: Integer read fTimeOut;
    property PoolInUseObjTimeOut: Integer read fTimeOut2;
end;


implementation

{ TAdoQueryPool }

constructor TAdoQueryPool.Create;
var
  index: Integer;
begin
  fAdoQueryMin := 10;
  fAdoQueryMax := 500;
  fRefreshTime := 3000;
  fTimeOut := 5000;
  fTimeOut2 := 1800000;

  fAdoQueryList := TComponentList.Create(False);   // 创建对象容器

  fCleanTimer := TTimer.Create(Self);
  fCleanTimer.Name := 'MyCleanTimer1';
  fCleanTimer.Interval :=fRefreshTime;
  fCleanTimer.OnTimer := fCleanOnTime;
  fCleanTimer.Enabled := True;
end;

destructor TAdoQueryPool.Destroy;
var
  i: integer;
begin
  for i := fAdoQueryList.Count - 1 downto 0 do
    TADOQuery(fAdoQueryList[i]).Free;

  fAdoQueryList.Free;
  fAdoQueryList := nil;

  inherited;
end;

procedure TAdoQueryPool.fClean;
var
  iNow : Integer;
  index : Integer;
begin
  iNow := GetTickCount;                                // 获取当前时间
  for index := fAdoQueryList.Count - 1 downto 0 do     // 轮询对象池
  begin
    if TADOQuery(fAdoQueryList[index]).Tag > 0 then    // 非使用中对象
    begin
      if fAdoQueryList.Count > fAdoQueryMin then       // 对象池内对象总数 > 对象池最小对象保留数量
      if iNow - TADOQuery(fAdoQueryList[index]).Tag > fTimeOut then  // 超时
        TADOQuery(fAdoQueryList[index]).Free;
    end
    else if TAdoQuery(fAdoQueryList[index]).Tag < 0 then      // 使用中对象
    begin
      if iNow + TADOQuery(fAdoQueryList[index]).Tag > ftimeOut2 then // 超时
      begin
        TADOQuery(fAdoQueryList[index]).Free;                       // 释放对象
        if fAdoQueryList.Count < fAdoQueryMin then                // 对象池对象总数 < 对象池最小保留对象
          fAdoQueryList.Add(fCreateADOQuery);                    // 对象池内创建新对象
      end;
    end;
  end;
end;

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

function TAdoQueryPool.fCreateADOQuery: TADOQuery;
begin
  Result := TADOQuery.Create(Self);
  Result.Tag := GetTickCount;
  Result.ConnectionString := 'FILE NAME='+extractfilepath(Application.ExeName)+'connect.udl';
end;

function TAdoQueryPool.GetAdoQuery: TADOQuery;
var
  index: Integer;
begin
  Result := nil;

  if fAdoQueryList.Count = 0 then                        //池中没有任何对象
  begin
    Result := fCreateADOQuery;                           // 创建新对象
    Result.Tag := - GetTickCount;                        // 标记为使用中
    fAdoQueryList.Add(Result);                           // 放入对象池内
    Exit;
  end;

  for index := 0 to fAdoQueryList.Count - 1 do           // 轮询对象池
  begin
    if TADOQuery(fAdoQueryList[index]).Tag > 0 then      // 非使用中对象
    begin
      Result := TADOQuery(fAdoQueryList[index]);
      Result.Tag := - GetTickCount;                      // 标记为使用中
      Break;
    end;
  end;

  if (Result = nil) and (index < fAdoQueryMax) then      // 对象池内已经没有非使用中对象
  begin
    Result := fCreateADOQuery;                           // 创建新对象
    Result.Tag := - GetTickCount;                        // 标记为使用中
    fAdoQueryList.Add(Result);                           // 放入对象池内
  end;
end;

function TAdoQueryPool.GetPoolSize: Integer;
begin
  Result := fAdoQueryList.Count;
end;

procedure TAdoQueryPool.returnAdoQuery(qry: TADOQuery);
begin
  if fAdoQueryList.IndexOf(qry) <> -1 then
    qry.Tag := GetTickCount;                             // 标记为非使用中对象
end;

end.

posted @ 2009-06-26 15:03  delphi中间件  阅读(927)  评论(0编辑  收藏  举报