zoukankan      html  css  js  c++  java
  • DIOCP开源项目-数据库连接池的使用<多帐套数据库>

           很久没有写DIOCP的Demo了,主要公司的事情太繁琐,工作之余都不想动了,之前承若的群里面朋友们的DEMO,昨天晚上恶补了一下,把对数据库连接池的操作加入到了Demo中,大家可以通过SVN下载到最新的代码和Demo。

           好了我带大家看看这次的DEMO,经过群里面朋友们的推荐,这次代码中引用了UntCobblerUniPool连接池代码来完成的本次的DEMO,研究了下代码,里面使用的线程时钟来做死连和多余连接的释放。感谢UntCobblerUniPool作者无私奉献的精神。

          先截个图,看看服务端的界面。

    image

    主要加入了多帐套的连接的配置。配置文件存放在configdbpool.config,是一个json格式的文件配置

    {
    "account2013": {
      "connString": "Provider Name=SQL Server;Data Source=192.168.1.2;Database=xxxx;User ID=sa;Password=sa"
    },
    "account2012": {
      "connString": "Provider Name=SQL Server;Data Source=192.168.1.2;Database=xxx02;User ID=sa;Password=sa"
    }
    }

    DEMO中我演示了两个帐套(实际运行中帐套个数是不固定),account2013和account2012代表帐套的ID,在clientContext中可以通过客户端传递过来的帐套ID,获取连接字符串,到连接池中获取一个连接。

    看看服务端的代码

    procedure TClientContext.dataReceived(const pvDataObject:TObject);
    var
      lvJsonStream:TJSonStream;
      lvFile:String;
      lvCmdIndex:Cardinal;
      lvXMLData, lvEncodeData:AnsiString;
      lvSQL, lvID:String;
      lvDBDataOperator:TUniOperator;
      lvPoolObj:TUniCobbler;
    
    begin
      lvJsonStream := TJSonStream(pvDataObject);
      try
        lvCmdIndex := lvJsonStream.JSon.I['cmdIndex'];
    
        //执行SQL的命令ID
        if lvCmdIndex= 1001 then
        begin
          //客户端传递过来的帐套ID
          lvID := lvJsonStream.Json.S['config.accountID'];
          if lvID = '' then
          begin
            raise Exception.Create('没有指定帐套ID(config.accountID)');
          end;
    
          //客户端指定要执行的SQL
          lvSQL := lvJsonStream.Json.S['script.sql'];
          if lvSQL = '' then
          begin
            raise Exception.Create('没有指定要执行的SQL!');
          end;
    
          //通过帐套ID获取一个连接池对象
          lvPoolObj := TUniPool.getConnObject(lvID);
          try
            //打开连接
            lvPoolObj.checkConnect;
    
            //Uni数据库操作对象<可以改用对象池效率更好>
            lvDBDataOperator := TUniOperator.Create;
            try
              //设置使用的连接池
              lvDBDataOperator.Connection := lvPoolObj.ConnObj;
              self.StateINfo := '借用了一个lvADOOpera,准备打开连接!';
              try
                //获取一个查询的数据
                lvXMLData := lvDBDataOperator.CDSProvider.QueryXMLData(lvSQL);
                self.StateINfo := 'lvADOOpera,执行SQL语句完成,准备回写数据';
              except
                raise;
              end;
    
              lvJsonStream.Clear();
              lvJsonStream.Stream.WriteBuffer(lvXMLData[1], Length(lvXMLData));
              lvJsonStream.setResult(True);
            finally
              lvDBDataOperator.Free;
            end;
          finally
            //归还连接池
            TUniPool.releaseConnObject(lvPoolObj);
          end;
          //回写数据给客户端
          writeObject(lvJsonStream);
        end else
        begin
          //返回数据
          writeObject(lvJsonStream);
        end;
      except
        on E:Exception do
        begin
          lvJsonStream.Clear();
          lvJsonStream.setResult(False);
          lvJsonStream.setResultMsg(e.Message);
          writeObject(lvJsonStream);
        end;
    
      end;
    end;


    注释写的比较清楚了,我就不再解释了,其他关联代码可以具体去看各单元的代码。

    看看客户端界面。

    image

    客户端通过指定帐套ID,告诉服务端应该选用哪个数据库进行操作。

    客户端执行的代码

    procedure TfrmMain.btnOpenSQLClick(Sender: TObject);
    var
      lvRecvObj, lvSendObj:TJsonStream;
      i, l, lvSize:Integer;
      lvData:AnsiString;
    begin
      lvSendObj := TJsonStream.Create;
      lvRecvObj := TJsonStream.Create;
      try
        lvSendObj.Clear();
    
        //帐套ID
        lvSendObj.Json.S['config.accountID'] := txtAccount.Text;
    
        //执行SQL的命令ID
        lvSendObj.Json.I['cmdIndex'] := 1001;
    
        //要执行的SQL
        lvSendObj.Json.S['script.sql'] := mmoSQL.Lines.Text;
    
        //发送到服务端进行处理<使用Indy进行传输>,如果需要使用ICS,可以在IOCPCoder文件夹中找到对应的uICSClientJSonStreamCoder.pas单元
        TIdTcpClientJSonStreamCoder.Encode(self.IdTCPClient, lvSendObj);
    
        //接收服务端处理的数据<使用Indy接收数据>
        TIdTcpClientJSonStreamCoder.Decode(self.IdTCPClient, lvRecvObj);
        if not lvRecvObj.getResult then
        begin
          raise Exception.Create(lvRecvObj.getResultMsg);
        end;
    
        //获取数据
        SetLength(lvData, lvRecvObj.Stream.Size);
        lvRecvObj.Stream.Position := 0;
        lvRecvObj.Stream.ReadBuffer(lvData[1], lvRecvObj.Stream.Size);
    
        //放入CDS的XMLDATA
        cdsMain.XMLData := lvData;
      finally
        lvSendObj.Free;
        lvRecvObj.Free;
      end;
    end;

    在DIOCPDemosIOCPCoder代码中我写了一些客户端的界面和编码器,有ICS,和Indy的,有需要的朋友可以直接引用使用。

             基本上差不多了。刚刚群里面的朋友测试在XE4下面测试是通过的,我的环境是D2007。

    >>>>>>DIOCP讨论群:320641073

    >>>>>>SVN源码和DEMO下载:https://code.google.com/p/diocp/

  • 相关阅读:
    MySQL学习笔记:coalesce
    Oracle学习笔记:decode函数
    MySQL学习笔记:like和regexp的区别
    状态图
    构件图和部署图
    java基础知识(一)
    包图
    活动图
    协作图
    序列图
  • 原文地址:https://www.cnblogs.com/DKSoft/p/3325819.html
Copyright © 2011-2022 走看看