• 数据库连接池类


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

  • 相关阅读:
    pagehide、beforeunload、unload
    script error
    fingerprintjs
    nodejs 加解密
    http
    stack
    csp
    btoa
    nginx文件上传模块 nginx_upload_module
    keepalived检测UDP端口
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/2940772.html
Copyright © 2020-2023  润新知