AdoConnection连接池的使用

[delphi]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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;  
  223.   
  224.   
  225. { TADOPool }  
  226. constructor TADOPool.Create(const MaxNumBer:Integer;FreeMinutes :Integer= 60;TimerTime:Integer = 5000);  
  227. begin  
  228.   InitializeCriticalSection(FSection);  
  229.   FPOOLNUMBER := MaxNumBer; //设置池大小  
  230.   FPollingInterval := FreeMinutes;// 连接池中  FPollingInterval 以上没用的 自动回收连接池  
  231.   FList := TList.Create;  
  232.   FTime := TTimer.Create(nil);  
  233.   FTime.Enabled := False;  
  234.   FTime.Interval := TimerTime;//5秒检查一次  
  235.   FTime.OnTimer := OnMyTimer;  
  236.   FTime.Enabled := True;  
  237. end;  
  238.   
  239. destructor TADOPool.Destroy;  
  240. var  
  241.   i:integer;  
  242. begin  
  243.   FTime.OnTimer := nil;  
  244.   FTime.Free;  
  245.   for i := FList.Count - 1 downto 0  do  
  246.   begin  
  247.     try  
  248.       FADOCon := TADOCon(FList.Items[i]);  
  249.       if Assigned(FADOCon) then  
  250.          FreeAndNil(FADOCon);  
  251.       FList.Delete(i);  
  252.     except  
  253.     end;  
  254.   end;  
  255.   FList.Free;  
  256.   DeleteCriticalSection(FSection);  
  257.   inherited;  
  258. end;  
  259.   
  260. procedure TADOPool.Enter;  
  261. begin  
  262.   EnterCriticalSection(FSection);  
  263. end;  
  264.   
  265. procedure TADOPool.Leave;  
  266. begin  
  267.   LeaveCriticalSection(FSection);  
  268. end;  
  269.   
  270. //根据字符串连接参数 取出当前连接池可以用的TADOConnection  
  271. function TADOPool.GetCon(const tmpConfig :TADOConfig):TADOConnection;  
  272. var  
  273.   i:Integer;  
  274.   IsResult :Boolean; //标识  
  275.   CurOutTime:Integer;  
  276. begin  
  277.   Result := nil;  
  278.   IsResult := False;  
  279.   CurOutTime := 0;  
  280.   Enter;  
  281.   try  
  282.     for I := 0 to FList.Count - 1 do  
  283.     begin  
  284.       FADOCon := TADOCon(FList.Items[i]);  
  285.       if not FADOCon.UseFlag then //可用  
  286.         if SameConfig(tmpConfig,FADOCon) then  //找到  
  287.         begin  
  288.           FADOCon.UseFlag := True; //标记已经分配用了  
  289.           Result :=  FADOCon.ConnObj;  
  290.           IsResult := True;  
  291.           Break;//退出循环  
  292.         end;  
  293.     end// end for  
  294.   finally  
  295.     Leave;  
  296.   end;  
  297.   if IsResult then Exit;  
  298.   //池未满 新建一个  
  299.   Enter;  
  300.   try  
  301.     if FList.Count < FPOOLNUMBER then //池未满  
  302.     begin  
  303.       FADOCon := TADOCon.Create(tmpConfig);  
  304.       FADOCon.UseFlag := True;  
  305.       Result :=  FADOCon.ConnObj;  
  306.       IsResult := True;  
  307.       FList.Add(FADOCon);//加入管理队列  
  308.     end;  
  309.   finally  
  310.     Leave;  
  311.   end;  
  312.   if IsResult then Exit;  
  313.   //池满 等待 等候释放  
  314.   while True do  
  315.   begin  
  316.     Enter;  
  317.     try  
  318.       for I := 0 to FList.Count - 1 do  
  319.       begin  
  320.         FADOCon := TADOCon(FList.Items[i]);  
  321.         if SameConfig(tmpConfig,FADOCon) then  //找到  
  322.           if not FADOCon.UseFlag then //可用  
  323.           begin  
  324.             FADOCon.UseFlag := True; //标记已经分配用了  
  325.             Result :=  FADOCon.ConnObj;  
  326.             IsResult := True;  
  327.             Break;//退出循环  
  328.           end;  
  329.       end// end for  
  330.       if IsResult then Break; //找到退出  
  331.     finally  
  332.       Leave;  
  333.     end;  
  334.     //如果不存在这种字符串的池子 则 一直等到超时  
  335.     if CurOutTime >= 5000 * 6 then  //1分钟  
  336.     begin  
  337.       raise Exception.Create('连接超时!');  
  338.       Break;  
  339.     end;  
  340.     Sleep(500);//0.5秒钟  
  341.     CurOutTime := CurOutTime + 500//超时设置成60秒  
  342.   end;//end while  
  343. end;  
  344.   
  345. procedure TADOPool.PutCon(const ADOConnection :TADOConnection);  
  346. var i :Integer;  
  347. begin  
  348.   { 
  349.   if not Assigned(ADOConnection) then Exit; 
  350.   try 
  351.     Enter; 
  352.     ADOConnection.Tag := 0;  //如此应该也可以 ,未测试... 
  353.   finally 
  354.     Leave; 
  355.   end; 
  356.   }  
  357.   Enter;  //并发控制  
  358.   try  
  359.     for I := FList.Count - 1 downto 0 do  
  360.     begin  
  361.       FADOCon := TADOCon(FList.Items[i]);  
  362.       if FADOCon.ConnObj=ADOConnection then  
  363.       begin  
  364.         FADOCon.UseFlag := False;  
  365.         Break;  
  366.       end;  
  367.     end;  
  368.   finally  
  369.     Leave;  
  370.   end;  
  371. end;  
  372.   
  373. procedure TADOPool.FreeConnection;  
  374. var  
  375.   i:Integer;  
  376.   function MyMinutesBetween(const ANow, AThen: TDateTime): Integer;  
  377.   begin  
  378.     Result := Round(MinuteSpan(ANow, AThen));  
  379.   end;  
  380. begin  
  381.   Enter;  
  382.   try  
  383.     for I := FList.Count - 1 downto 0 do  
  384.     begin  
  385.       FADOCon := TADOCon(FList.Items[i]);  
  386.       if MyMinutesBetween(Now,FADOCon.AStart) >= FPollingInterval then //释放池子许久不用的ADO  
  387.       begin  
  388.         FreeAndNil(FADOCon);  
  389.         FList.Delete(I);  
  390.       end;  
  391.     end;  
  392.   finally  
  393.     Leave;  
  394.   end;  
  395. end;  
  396.   
  397. procedure TADOPool.OnMyTimer(Sender: TObject);  
  398. begin  
  399.   FreeConnection;  
  400. end;  
  401.   
  402. function TADOPool.SameConfig(const Source:TADOConfig;Target:TADOCon): Boolean;  
  403. begin  
  404. //考虑到支持多数据库连接,需要本方法做如下等效连接判断.如果是单一数据库,可忽略本过程。  
  405. {  Result := False; 
  406.   if not Assigned(Source) then Exit; 
  407.   if not Assigned(Target) then Exit; 
  408.  
  409.   Result := SameStr(LowerCase(Source.ConnectionName),LowerCase(Target.ConnObj.Name)); 
  410.   Result := Result and SameStr(LowerCase(Source.DriverName),LowerCase(Target.ConnObj.Provider)); 
  411.   Result := Result and SameStr(LowerCase(Source.HostName),LowerCase(Target.ConnObj.Properties['Data Source'].Value)); 
  412.   Result := Result and SameStr(LowerCase(Source.DataBase),LowerCase(Target.ConnObj.Properties['Initial Catalog'].Value)); 
  413.   Result := Result and SameStr(LowerCase(Source.UserName),LowerCase(Target.ConnObj.Properties['User ID'].Value)); 
  414.   Result := Result and SameStr(LowerCase(Source.PassWord),LowerCase(Target.ConnObj.Properties['Password'].Value)); 
  415.   //Result := Result and (Source.OSAuthentication = Target.ConnObj.OSAuthentication); 
  416.   }  
  417. end;  
  418.   
  419. Function TADOPool.GetConnectionCount :Integer;  
  420. begin  
  421.   Result := FList.Count;  
  422. end;  
  423. //初始化时创建对象  
  424. initialization  
  425.   //ini文件后缀更名为LXH,方便远程安全下载更新  
  426.   ADOConfig := TADOConfig.Create(ExtractFilePath(ParamStr(0))+'SERVERDB.LXH');  
  427.   ADOPool := TADOPool.Create(15);  
  428. finalization  
  429.   if Assigned(ADOPool) then ADOPool.Free;  
  430.   if Assigned(ADOConfig) then ADOConfig.Free;  
  431.   
  432. end.  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值