//==============================================================================
// TADOQuery池 咏南工作室 2008-10-06 14:22:35
//==============================================================================
unit UAdoQueryPool;
interface
uses
SysUtils, Classes, DB, ADODB, Contnrs, Windows, ExtCtrls;
type
RQueryParams=record
QueryMin:Integer; //池中对象最小数 10
QueryMax:Integer; //池中对象最大数 100
TimerTime:Integer; //清理程序启动的时间间隔 600000(10分钟)
end;
type
TAdoQueryPool = class(TComponent) //AdoQuery缓冲池类
private
fAdoQueryMin : Integer;
fAdoQueryMax : Integer;
fAdoQueryList : TComponentList;
fCleanTimer : TTimer;
fQueryParams:RQueryParams;
procedure fCleanOnTime(sender : TObject); //按时整理缓冲池
function fCreateADOQuery : TADOQuery; //创建新的AdoQuery
procedure fClean; //整理 (清理长时间不用的和长时间不归还的AdoQuery)
{ Private declarations }
public
{ Public declarations }
constructor Create(owner : TComponent;QueryParams:RQueryParams);
function getAdoQuery : TADOQuery; //取得空闲TADOQuery
procedure returnAdoQuery(qry : TADOQuery); //归还
end;
implementation
{ TAdoQueryPool }
constructor TAdoQueryPool.Create(owner: TComponent;QueryParams:RQueryParams);
var
index : Integer;
aAdoQuery : TADOQuery;
begin
fQueryParams:=QueryParams;
fAdoQueryMin := fQueryParams.QueryMin;
fAdoQueryMax := fQueryParams.QueryMax;
fAdoQueryList := TComponentList.Create(False);
for index := 1 to fAdoQueryMin do
fAdoQueryList.Add(fCreateADOQuery);
if fCleanTimer = nil then
begin
fCleanTimer := TTimer.Create(Self);
fCleanTimer.Name := 'MyCleanTimer1';
fCleanTimer.Interval :=fQueryParams.TimerTime; //清理程序启动的时间间隔(10分钟)
fCleanTimer.OnTimer := fCleanOnTime;
fCleanTimer.Enabled := True;
end;
end;
procedure TAdoQueryPool.fClean;
var
iNow : Integer; //当前时刻
iCount : Integer; //List大小
index : Integer;
begin
iNow := GetTickCount;
iCount := fAdoQueryList.Count;
for index := iCount - 1 downto 0 do
begin
if TADOQuery(fAdoQueryList[index]).Tag > 0 then //若空闲
begin
if fAdoQueryList.Count > fAdoQueryMin then //若AdoQuery个数大于最小值
begin
TADOQuery(fAdoQueryList[index]).Free;
end
else if TAdoQuery(fAdoQueryList[index]).Tag < 0 then
begin
if iNow + TADOQuery(fAdoQueryList[index]).Tag > 10800000 then //被连续使用超过3小时的AdoQuery(很可能是死的),释放
begin
TADOQuery(fAdoQueryList[index]).Free;
if fAdoQueryList.Count < fAdoQueryMin then//若小于缓冲池最小数目,则创建新的空闲AdoQuery
fAdoQueryList.Add(fCreateADOQuery);
end;
end;
end;
end;
end;
procedure TAdoQueryPool.fCleanOnTime(sender: TObject);
begin
fClean;
end;
function TAdoQueryPool.fCreateADOQuery: TADOQuery;
begin
Result := TADOQuery.Create(Self);
Result.Tag := GetTickCount; //空闲,开始计时(正数表示空闲)
end;
function TAdoQueryPool.getAdoQuery: TADOQuery;
var
index : Integer;
begin
Result := nil;
for index := 0 to fAdoQueryList.Count - 1 do
begin
if TADOQuery(fAdoQueryList[index]).Tag > 0 then
begin
Result := TADOQuery(fAdoQueryList[index]);
Result.Tag := - GetTickCount; //使用开始计时 (负数表示正在使用)
end;
end;
if (Result = nil) and (index < fAdoQueryMax) then//无空闲AdoQuery,而缓冲池数目小于允许最大数目(fAdoQueryMax),创建新的Adoquery
begin
Result := fCreateADOQuery;
Result.Tag := - GetTickCount; //使用,开始计时 (负数表示正在使用)
fAdoQueryList.Add(Result);
end;
end;
procedure TAdoQueryPool.returnAdoQuery(qry: TADOQuery);
begin
if fAdoQueryList.IndexOf(qry) > -1 then
qry.Tag := GetTickCount; //开始空闲计时
end;
end.