• KBMMW SampleService/SampleClient方式传输数据集


    马上周末了,趁着下午这会儿回顾一下这几天对旧项目的升级过程,一些重要但不常用的东西记录下来是很有必要的。其中一个项目中对KBMMW的远程数据通讯方式做了改进,利用SampleService/SampleClient方式传输数据集,以增加对底层数据通讯的可控性。

    服务端代码示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    type
      TkbmMWSimpleService1 = class(TkbmMWSimpleService)
      private
         { Private declarations }
      protected
         { Protected declarations }
         function ProcessRequest(const Func:string; const ClientIdent:TkbmMWClientIdentity; const Args:array of Variant):Variant; override;
         function PerformOpenSQL(ClientIdent:TkbmMWClientIdentity; const Args:array of Variant):Variant; virtual;
     
      public
         { Public declarations }
    {$IFNDEF CPP}class{$ENDIF} function GetFlags:TkbmMWServiceFlags; override;
      end;
     
    //...省略
     
    function TkbmMWSimpleService1.ProcessRequest(const Func:string; const ClientIdent:TkbmMWClientIdentity; const Args:array of Variant):Variant;
    var
       AFunc:string;
    begin
         AFunc:=UpperCase(Func);
         if AFunc='OPENSQL' then
            Result:=PerformOpenSQL(ClientIdent,Args)
         else Result:=inherited ProcessRequest(Func,ClientIdent,Args);
    end;
     
    function TkbmMWSimpleService1.PerformOpenSQL(ClientIdent:TkbmMWClientIdentity; const Args:array of Variant):Variant;
    var
      sqlStr: string;
      aQuery: TUniQuery;
      aconn: TkbmMWUNIDACConnection;
      memTable: TkbmMemTable;
      aStreamFormat: TkbmBinaryStreamFormat;
    begin
      Result := 0;
      sqlStr:=args[0];
      aQuery := TUniQuery.Create(nil);//uniquery,和两层的用法一样
      aQuery.Options.QueryRecCount := True;
      aconn := TkbmMWUNIDACConnection(DMunt.kbmMWUNIDACConnectionPool1.GetBestConnection(True,0,nil,10000));//取连接池中的连接
      if aconn = nil then
      begin
        kbmMWRaiseServerException('无可用的数据库连接');
        Exit;
      end;
      aQuery.Connection := aconn.Database;
      aQuery.SQL.Text := sqlStr;
      if (mainform.PAL_mode_01.Visible) then
        LogIOer.AddShow(ClientIdent.Username+'执行SQL查询:'+aQuery.SQL.Text,0);
      memTable := TkbmMemTable.Create(nil);
      aStreamFormat := TkbmBinaryStreamFormat.Create(nil);
      memTable.DefaultFormat := aStreamFormat;
      memTable.IndexFieldNames := '';
      memTable.SortFields := '';
      memTable.MasterSource := nil;
      try
        try
          aQuery.Open;//查询
          Result := aQuery.RecordCount;//返回记录条数
        except
          on E:Exception do
          begin
            kbmMWRaiseServerException(E.Message+',异常语句:'+aQuery.SQL.Text);//抛异常到客户端
            Exit;
          end;
        end;
        memTable.LoadFromDataSet(aQuery,[mtcpoStructure,mtcpoProperties]); //复制数据集进KbMemTable
        memTable.SaveToStreamViaFormat(ResultStream,aStreamFormat); //按照指定流格式存入结果流ResultStream
      finally
        aconn.UnlockConnection;
        aQuery.Free;
        memTable.Free;
        aStreamFormat.Free;
      end;
    end;

    客户端代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    function openSql(Sqlstr:string;var Ds:TDataSet;var Rs:string):integer;stdcall;
      var
        args: array[0..1] of Variant;
      begin
        Result := 0;
        Rs := '执行成功';
        if assigned(kbmMWSimpleClient1) then
        begin
          try
            args[0]:= Sqlstr;//SQL语句
            Result := kbmMWSimpleClient1.Request('TkbmMWSimpleService1','','openSql',args);//SimpleClient执行请求
            kbmMemTable.EmptyTable;//清空内存表
            kbmMemTable.LoadFromStreamViaFormat(kbmMWSimpleClient1.ResultStream,aStreamFormat);//将结果流复制进内存表
            ds := kbmMemTable;//返回dataset(kbmMemTable继承自Tdataset)
          except
            on E:Exception do
            begin
              Result := -1;
              rs := errorInfo(E.Message);
              if FIsLog then Writelog(rs);
            end;
          end;
        end
        else
        begin
          Result := -1;//未执行初始化操作
          Rs := '远程数据通讯接口未执行初始化操作'
        end;
      end;

    核心代码就这些,相信用到的人能够看明白。同理,可以利用这种方式实现二进制文件流(如:图像等)的传输,不再赘述。
    另外,有一个小问题折磨了我一下午,提醒大家一下,希望大家不要像我一样粗心:
    有两个类:TkbmBinaryStreamFormat(kbmMemBinaryStreamFormat.pas)、TkbmMWBinaryStreamFormat(kbmMWBinaryStreamFormat.pas)很容易混淆(正确用法见上述代码),而且一旦混淆,会造成KbmMeMTable在流的处理过程中出错。

    http://www.pfeng.org/archives/385

  • 相关阅读:
    【rust】Rust 的构建系统和包管理工具Cargo认识并初步使用(2)
    【rust】rust安装,运行第一个Rust 程序 (1)
    linux 双网卡桥接,实现网卡流量镜像与转发
    【原创】使用golang访问windows telnet服务器
    使用centos 7安装conpot
    用Redis作Mysql数据库缓存
    python解析处理snmp回显----snmp
    snmp自定义OID与文件下载----服务器端配置
    golang map输出排序
    计算机组成原理---第1章 计算机系统概述
  • 原文地址:https://www.cnblogs.com/findumars/p/5111784.html
Copyright © 2020-2023  润新知