AdoConnection连接池的使用

  1. (******************************************************************************* 
  2.   ADOConnection连接池 
  3.  
  4.    池满的情况下 池子ADO连接 动态创建 
  5.  
  6.    系统默认池子中 一个小时以上未用的 ADOConnection 连接 系统自动释放 
  7.  
  8.    使用如下 
  9.    先Uses SQLADOPoolUnit 单元 
  10.  
  11.    在程序初始化时(initialization)创建连接池类 
  12.    ADOConfig := TADOConfig.Create('SERVERDB.LXH'); 
  13.    ADOXPool := TADOPool.Create(15); 
  14.  
  15.    在程序关闭时(finalization)释放连接池类 
  16.    ADOPool.Free; 
  17.    ADOConfig.Free; 
  18.  
  19.    调用如下 
  20.   try 
  21.     ADOQuery.Connecttion:= ADOPool.GetCon(ADOConfig); 
  22.     ADOQueryt.Open; 
  23.   finally 
  24.     ADOPool.PutCon(ADOQuery.Connecttion); 
  25.   end; 
  26.  
  27. 作者:何应祖(QQ:306446305) 
  28.   2012-10 
  29. 如有优化 请传作者一份 。谢谢! 
  30.  
  31. ********************************************************************************)  
  32.   
  33. unit SQLADOPoolUnit;  
  34.   
  35. interface  
  36.   
  37. uses  
  38.   Winapi.Windows,Data.SqlExpr,System.SysUtils, System.Classes,Vcl.ExtCtrls, System.DateUtils,Data.DB, Data.Win.ADODB,System.IniFiles,  
  39.   Winapi.Messages, Datasnap.Provider, Data.DBXMSSQL;  
  40.   
  41. type// 数据库类型  
  42.   TDBType=(Access,SqlServer,Oracle);  
  43.   
  44. //数据库配置   ADO  
  45. type  
  46.   TADOConfig = class  
  47.     //数据库配置  
  48.     ConnectionName :string;//连接驱动名字  
  49.     ProviderName :string;//通用驱动  
  50.     DBServer:string;  //数据源 --数据库服务器IP  
  51.     DataBase :string; //数据库名字  //sql server连接时需要数据库名参数--数据库实例名称  
  52.     OSAuthentication:Boolean;  //是否是windows验证  
  53.     UserName :string; //数据库用户  
  54.     PassWord :string; //密码  
  55.     AccessPassWord:string;  //Access可能需要数据库密码  
  56.     Port:integer;//数据库端口  
  57.     //  
  58.     DriverName :string;//驱动  
  59.     HostName :string;//服务地址  
  60.     //端口配置  
  61.     TCPPort:Integer; //TCP端口  
  62.     HttpPort:Integer; //http 端口  
  63.     LoginSrvUser:string;//验证中间层服务登录用户  
  64.     LoginSrvPassword:string;//验证登录模块密码  
  65.   public  
  66.     constructor Create(iniFile :String);overload;  
  67.     destructor Destroy; override;  
  68.   end;  
  69.   
  70. type  
  71.   TADOCon = class  
  72.   private  
  73.     FConnObj:TADOConnection;  //数据库连接对象  
  74.     FAStart: TDateTime;        //最后一次活动时间  
  75.   
  76.     function GetUseFlag: Boolean;  
  77.     procedure SetUseFlag(value: Boolean);  
  78.   public  
  79.     constructor Create(ADOConfig :TADOConfig);overload;  
  80.     destructor Destroy;override;  
  81.     //当前对象是否被使用  
  82.     property UseFlag :boolean read GetUseFlag write SetUseFlag ;  
  83.     property ConnObj :TADOConnection read FConnObj;  
  84.     property AStart :TDateTime read FAStart write FAStart;  
  85.   end;  
  86.   
  87. type  
  88.   TADOPool = class  
  89.     procedure OnMyTimer(Sender: TObject);//做轮询用  
  90.   private  
  91.     FSection :TRTLCriticalSection;  
  92.     FPoolNumber :Integer;     //池大小  
  93.     FPollingInterval :Integer;//轮询时间 以 分 为单位  
  94.     FADOCon :TADOCon;  
  95.     FList :TList;             //用来管理连接TADOCobbler  
  96.     FTime :TTimer;            //主要做轮询  
  97.     procedure Enter;  
  98.     procedure Leave;  
  99.     function SameConfig(const Source:TADOConfig; Target:TADOCon):Boolean;  
  100.     function GetConnectionCount: Integer;  
  101.   public  
  102.     constructor Create(const MaxNumBer:Integer;FreeMinutes :Integer= 60;TimerTime:Integer = 5000);overload;  
  103.     destructor Destroy;override;  
  104.     //从池中取出可用的连接。  
  105.     function GetCon(const tmpConfig :TADOConfig):TADOConnection;  
  106.     //把用完的连接放回连接池。  
  107.     procedure PutCon(const ADOConnection :TADOConnection);  
  108.     //释放池中许久未用的连接,由定时器定期扫描执行  
  109.     procedure FreeConnection;  
  110.     //当前池中连接数.  
  111.     property ConnectionCount: Integer read GetConnectionCount;  
  112.   end;  
  113.   
  114. var  
  115.   ADOPool: TADOPool;  
  116.   ADOConfig: TADOConfig;  
  117. implementation  
  118.   
  119. { TADOConfig }  
  120. constructor TADOConfig.Create(iniFile :String);  
  121. var  
  122.   DBIniFile: TIniFile;  
  123. begin  
  124.   try  
  125.     DBIniFile := TIniFile.Create(iniFile);  
  126.     ConnectionName := DBIniFile.ReadString('Connection','ConnectionName', 'SQLConnection');  
  127.     DriverName := DBIniFile.ReadString('Connection','DriverName', 'MSDASQL');  
  128.     ProviderName := DBIniFile.ReadString('Connection','ProviderName', 'MSDASQL');  
  129.     DBServer:= DBIniFile.ReadString('Connection','DBServer', '127.0.0.1');  
  130.     HostName := DBIniFile.ReadString('Connection','HostName', '127.0.0.1');  
  131.     DataBase := DBIniFile.ReadString('Connection','DataBase', 'GPMS2000');  
  132.     Port:=DBIniFile.ReadInteger('Connection','Port', 1433);  
  133.     UserName := DBIniFile.ReadString('Connection','UserName', 'Sa');  
  134.     PassWord := DBIniFile.ReadString('Connection','PassWord', 'Sa');  
  135.     LoginSrvUser := DBIniFile.ReadString('Connection','LoginSrvUser', 'hyz');  
  136.     LoginSrvPassword := DBIniFile.ReadString('Connection','LoginSrvPassword', 'hyz');  
  137.     TCPPort := DBIniFile.ReadInteger('Connection','TCPPort', 211);  
  138.     HttpPort := DBIniFile.ReadInteger('Connection','HttpPort', 2110);  
  139.     OSAuthentication := DBIniFile.ReadBool('Connection','OSAuthentication', False);  
  140.   
  141.     if Not FileExists(iniFile) then  
  142.     begin  
  143.       If Not DirectoryExists(ExtractFilePath(iniFile)) Then ForceDirectories(ExtractFilePath(iniFile));  
  144.       DBIniFile.WriteString('Connection','ConnectionName', ConnectionName);  
  145.       DBIniFile.WriteString('Connection','DriverName', DriverName);  
  146.       DBIniFile.WriteString('Connection','HostName', HostName);  
  147.       DBIniFile.WriteString('Connection','DBServer', HostName);  
  148.       DBIniFile.WriteString('Connection','DataBase', DataBase);  
  149.  //     DBIniFile.WriteString('Connection','Port',Port);  
  150.       DBIniFile.WriteString('Connection','UserName', UserName);  
  151.       DBIniFile.WriteString('Connection','PassWord', PassWord);  
  152.       DBIniFile.WriteString('Connection','LoginSrvUser', LoginSrvUser);  
  153.       DBIniFile.WriteString('Connection','LoginSrvPassword', LoginSrvPassword);  
  154.       DBIniFile.WriteInteger('Connection','TCPPort', TCPPort);  
  155.       DBIniFile.WriteInteger('Connection','HttpPort', HttpPort);  
  156.       DBIniFile.WriteBool('Connection','OSAuthentication', OSAuthentication);  
  157.     end;  
  158.   finally  
  159.     FreeAndNil(DBIniFile);  
  160.   end;  
  161. end;  
  162.   
  163. destructor TADOConfig.Destroy;  
  164. begin  
  165.   inherited;  
  166. end;  
  167.   
  168. { TADOCon }  
  169. constructor TADOCon.Create(ADOConfig: TADOConfig);  
  170. //var  
  171. //  str:string;  
  172. begin  
  173. //  str:='Provider=SQLOLEDB.1;Persist Security Info=False;User ID='+ADOConfig.UserName+';password='+ADOConfig.PassWord+';Initial Catalog='+ADOConfig.DataBase+';Data Source='+ADOConfig.DBServer;  
  174.   FConnObj:=TADOConnection.Create(nil);  
  175.   with FConnObj do  
  176.   begin  
  177.     LoginPrompt:=False;  
  178.     Tag:=GetTickCount;  
  179.     ConnectionTimeout:=18000;  
  180.     Provider:=ADOConfig.ProviderName;  
  181.     Properties['Data Source'].Value:=ADOConfig.DBServer;  
  182.     Properties['User ID'].Value:=ADOConfig.UserName;  
  183.     Properties['Password'].Value:=ADOConfig.PassWord;  
  184.     Properties['Initial Catalog'].Value:=ADOConfig.DataBase;  
  185.   
  186. //    ConnectionString:=str;  
  187.     try  
  188.       Connected:=True;  
  189.     except  
  190.       raise Exception.Create('数据库连接失败');  
  191.     end;  
  192.   end;  
  193. end;  
  194.   
  195. destructor TADOCon.Destroy;  
  196. begin  
  197.   FAStart := 0;  
  198.   if Assigned(FConnObj) then  
  199.   BEGIN  
  200.     if FConnObj.Connected then FConnObj.Close;  
  201.     FreeAndnil(FConnObj);  
  202.   END;  
  203.   inherited;  
  204. end;  
  205.   
  206.   
  207. procedure TADOCon.SetUseFlag(value :Boolean);  
  208. begin  
  209.   //False表示闲置,True表示在使用。  
  210.   if not value then  
  211.     FConnObj.Tag := 0  
  212.   else  
  213.     begin  
  214.     if FConnObj.Tag = 0 then FConnObj.Tag := 1;  //设置为使用标识。  
  215.     FAStart := now;                              //设置启用时间 。  
  216.     end;  
  217. end;  
  218.   
  219. Function TADOCon.GetUseFlag :Boolean;  
  220. begin  
  221.   Result := (FConnObj.Tag>0);  //Tag=0表示闲置,Tag>0表示在使用。  
  222. end;  

//   AdoConnection连接池的使用(续)

  1. { TADOPool }  
  2. constructor TADOPool.Create(const MaxNumBer:Integer;FreeMinutes :Integer= 60;TimerTime:Integer = 5000);  
  3. begin  
  4.   InitializeCriticalSection(FSection);  
  5.   FPOOLNUMBER := MaxNumBer; //设置池大小  
  6.   FPollingInterval := FreeMinutes;// 连接池中  FPollingInterval 以上没用的 自动回收连接池  
  7.   FList := TList.Create;  
  8.   FTime := TTimer.Create(nil);  
  9.   FTime.Enabled := False;  
  10.   FTime.Interval := TimerTime;//5秒检查一次  
  11.   FTime.OnTimer := OnMyTimer;  
  12.   FTime.Enabled := True;  
  13. end;  
  14.   
  15. destructor TADOPool.Destroy;  
  16. var  
  17.   i:integer;  
  18. begin  
  19.   FTime.OnTimer := nil;  
  20.   FTime.Free;  
  21.   for i := FList.Count - 1 downto 0  do  
  22.   begin  
  23.     try  
  24.       FADOCon := TADOCon(FList.Items[i]);  
  25.       if Assigned(FADOCon) then  
  26.          FreeAndNil(FADOCon);  
  27.       FList.Delete(i);  
  28.     except  
  29.     end;  
  30.   end;  
  31.   FList.Free;  
  32.   DeleteCriticalSection(FSection);  
  33.   inherited;  
  34. end;  
  35.   
  36. procedure TADOPool.Enter;  
  37. begin  
  38.   EnterCriticalSection(FSection);  
  39. end;  
  40.   
  41. procedure TADOPool.Leave;  
  42. begin  
  43.   LeaveCriticalSection(FSection);  
  44. end;  
  45.   
  46. //根据字符串连接参数 取出当前连接池可以用的TADOConnection  
  47. function TADOPool.GetCon(const tmpConfig :TADOConfig):TADOConnection;  
  48. var  
  49.   i:Integer;  
  50.   IsResult :Boolean; //标识  
  51.   CurOutTime:Integer;  
  52. begin  
  53.   Result := nil;  
  54.   IsResult := False;  
  55.   CurOutTime := 0;  
  56.   Enter;  
  57.   try  
  58.     for I := 0 to FList.Count - 1 do  
  59.     begin  
  60.       FADOCon := TADOCon(FList.Items[i]);  
  61.       if not FADOCon.UseFlag then //可用  
  62.         if SameConfig(tmpConfig,FADOCon) then  //找到  
  63.         begin  
  64.           FADOCon.UseFlag := True; //标记已经分配用了  
  65.           Result :=  FADOCon.ConnObj;  
  66.           IsResult := True;  
  67.           Break;//退出循环  
  68.         end;  
  69.     end; // end for  
  70.   finally  
  71.     Leave;  
  72.   end;  
  73.   if IsResult then Exit;  
  74.   //池未满 新建一个  
  75.   Enter;  
  76.   try  
  77.     if FList.Count < FPOOLNUMBER then //池未满  
  78.     begin  
  79.       FADOCon := TADOCon.Create(tmpConfig);  
  80.       FADOCon.UseFlag := True;  
  81.       Result :=  FADOCon.ConnObj;  
  82.       IsResult := True;  
  83.       FList.Add(FADOCon);//加入管理队列  
  84.     end;  
  85.   finally  
  86.     Leave;  
  87.   end;  
  88.   if IsResult then Exit;  
  89.   //池满 等待 等候释放  
  90.   while True do  
  91.   begin  
  92.     Enter;  
  93.     try  
  94.       for I := 0 to FList.Count - 1 do  
  95.       begin  
  96.         FADOCon := TADOCon(FList.Items[i]);  
  97.         if SameConfig(tmpConfig,FADOCon) then  //找到  
  98.           if not FADOCon.UseFlag then //可用  
  99.           begin  
  100.             FADOCon.UseFlag := True; //标记已经分配用了  
  101.             Result :=  FADOCon.ConnObj;  
  102.             IsResult := True;  
  103.             Break;//退出循环  
  104.           end;  
  105.       end; // end for  
  106.       if IsResult then Break; //找到退出  
  107.     finally  
  108.       Leave;  
  109.     end;  
  110.     //如果不存在这种字符串的池子 则 一直等到超时  
  111.     if CurOutTime >= 5000 * 6 then  //1分钟  
  112.     begin  
  113.       raise Exception.Create('连接超时!');  
  114.       Break;  
  115.     end;  
  116.     Sleep(500);//0.5秒钟  
  117.     CurOutTime := CurOutTime + 500; //超时设置成60秒  
  118.   end;//end while  
  119. end;  
  120.   
  121. procedure TADOPool.PutCon(const ADOConnection :TADOConnection);  
  122. var i :Integer;  
  123. begin  
  124.   { 
  125.   if not Assigned(ADOConnection) then Exit; 
  126.   try 
  127.     Enter; 
  128.     ADOConnection.Tag := 0;  //如此应该也可以 ,未测试... 
  129.   finally 
  130.     Leave; 
  131.   end; 
  132.   }  
  133.   Enter;  //并发控制  
  134.   try  
  135.     for I := FList.Count - 1 downto 0 do  
  136.     begin  
  137.       FADOCon := TADOCon(FList.Items[i]);  
  138.       if FADOCon.ConnObj=ADOConnection then  
  139.       begin  
  140.         FADOCon.UseFlag := False;  
  141.         Break;  
  142.       end;  
  143.     end;  
  144.   finally  
  145.     Leave;  
  146.   end;  
  147. end;  
  148.   
  149. procedure TADOPool.FreeConnection;  
  150. var  
  151.   i:Integer;  
  152.   function MyMinutesBetween(const ANow, AThen: TDateTime): Integer;  
  153.   begin  
  154.     Result := Round(MinuteSpan(ANow, AThen));  
  155.   end;  
  156. begin  
  157.   Enter;  
  158.   try  
  159.     for I := FList.Count - 1 downto 0 do  
  160.     begin  
  161.       FADOCon := TADOCon(FList.Items[i]);  
  162.       if MyMinutesBetween(Now,FADOCon.AStart) >= FPollingInterval then //释放池子许久不用的ADO  
  163.       begin  
  164.         FreeAndNil(FADOCon);  
  165.         FList.Delete(I);  
  166.       end;  
  167.     end;  
  168.   finally  
  169.     Leave;  
  170.   end;  
  171. end;  
  172.   
  173. procedure TADOPool.OnMyTimer(Sender: TObject);  
  174. begin  
  175.   FreeConnection;  
  176. end;  
  177.   
  178. function TADOPool.SameConfig(const Source:TADOConfig;Target:TADOCon): Boolean;  
  179. begin  
  180. //考虑到支持多数据库连接,需要本方法做如下等效连接判断.如果是单一数据库,可忽略本过程。  
  181. {  Result := False; 
  182.   if not Assigned(Source) then Exit; 
  183.   if not Assigned(Target) then Exit; 
  184.  
  185.   Result := SameStr(LowerCase(Source.ConnectionName),LowerCase(Target.ConnObj.Name)); 
  186.   Result := Result and SameStr(LowerCase(Source.DriverName),LowerCase(Target.ConnObj.Provider)); 
  187.   Result := Result and SameStr(LowerCase(Source.HostName),LowerCase(Target.ConnObj.Properties['Data Source'].Value)); 
  188.   Result := Result and SameStr(LowerCase(Source.DataBase),LowerCase(Target.ConnObj.Properties['Initial Catalog'].Value)); 
  189.   Result := Result and SameStr(LowerCase(Source.UserName),LowerCase(Target.ConnObj.Properties['User ID'].Value)); 
  190.   Result := Result and SameStr(LowerCase(Source.PassWord),LowerCase(Target.ConnObj.Properties['Password'].Value)); 
  191.   //Result := Result and (Source.OSAuthentication = Target.ConnObj.OSAuthentication); 
  192.   }  
  193. end;  
  194.   
  195. Function TADOPool.GetConnectionCount :Integer;  
  196. begin  
  197.   Result := FList.Count;  
  198. end;  
  199. //初始化时创建对象  
  200. initialization  
  201.   //ini文件后缀更名为LXH,方便远程安全下载更新  
  202.   ADOConfig := TADOConfig.Create(ExtractFilePath(ParamStr(0))+'SERVERDB.LXH');  
  203.   ADOPool := TADOPool.Create(15);  
  204. finalization  
  205.   if Assigned(ADOPool) then ADOPool.Free;  
  206.   if Assigned(ADOConfig) then ADOConfig.Free;  
  207.   
  208. end.  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值