马上周末了,趁着下午这会儿回顾一下这几天对旧项目的升级过程,一些重要但不常用的东西记录下来是很有必要的。其中一个项目中对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

KBMMW SampleService/SampleClient方式传输数据集的更多相关文章

  1. Node.js初探之GET方式传输

    Node.js初探之GET方式传输 例子:form用GET方法向后台传东西 html文件: <form action="http://localhost:8080/aaa" ...

  2. 流,用声明性的方式处理数据集 - 读《Java 8实战》

    引入流 Stream API的代码 声明性 更简洁,更易读 可复合 更灵活 可并行 性能更好 流是什么? 它允许以声明方式处理数据集合 遍历数据集的高级迭代器 透明地并行处理 简短定义:从支持数据处理 ...

  3. C# Post方式传输报文,和处理响应

    public string DoPost(string url, string data) { HttpWebRequest req = GetWebRequest(url, "POST&q ...

  4. Node.js初探之POST方式传输

    小知识:POST比GET传输的数据量大很多 POST发数据--"分段" 实例: 准备一个form.html文件: <!DOCTYPE html> <html> ...

  5. ASP.NET WebServce项目下添加Http服务,支持Get,Post请求方式;传输格式json/xml

    由于WEBServce老项目中需要增添新的接口,而且添加的接口不希望被其它项目以引用Servces方式使用. 那么得在现有Service项目中添加Http请求方式来实现系统间数据交互.只需要告知请求地 ...

  6. http使用formData方式传输文件请求

    转载请注明出处: 项目中有遇到http使用formData请求传输文件,在此记录一下 1.依赖jar包: <dependency> <groupId>org.apache.ht ...

  7. 用socket方式传输Image和Sound文件

    import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.Obje ...

  8. cache支持single/increment/increment4三种方式传输

    1.cache bypass signle---data length 已知 increment ---data length 不知 用 last data address  结束数据传输 2.cac ...

  9. json和jsonp的传输方式

    jsonp传输会解决跨域的问题 $.ajax({ async: false, /* url: "http://127.0.0.1:8080/2015020601/background/mea ...

随机推荐

  1. oracle rman异机恢复

      Oracle源主机 Oracle目标主机 主机平台 CentOS6.2(final) CentOs6.2(FInal) 主机名 vick rman IP地址 192.168.1.11 192.16 ...

  2. c#学习心得,慢慢添加,如果有错误希望大家留言,我刚开始学

    1.class类:相当于整个项目的一个功能性程序,为了阐述系统中某个对象的功能. 方法:相当于程序的一个功能部件.可以被其他方法或类调用?感觉这个问题有点复杂 c#框架结构:我目前接触到的 using ...

  3. Android应用开发实例篇(1)-----简易涂鸦板

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/03/2378328.html 一.概述 这次要做一个简单的涂鸦板应用,以前在Qt上实现过,突然想 ...

  4. Java学习之equals和hashcode的关系

    两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对? 答:不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(has ...

  5. 不小心中了machook病毒

    此文运用的是优雅的Markdown而书 前段回家过年的日子,我心爱的小air在运行时不停的弹出"machook停止运行"的提醒,上网google一下不看不要紧,才得知是mac上的一 ...

  6. tmod命令

    tmod ./tpl --debug --no-watch --output ./tplbuild

  7. [LeetCode]题解(python):132-Palindrome Partitioning II

    题目来源: https://leetcode.com/problems/palindrome-partitioning-ii/ 题意分析: 给定一个s,可以将s拆成若干个回文子字符串之和,如果拆成了m ...

  8. linux如何关闭selinux?

    首先我们可以用命令来查看selinux的状态getenforce 这个命令可以查看到selinux的状态,当前可以看到是关闭状态的.还有一个命令也可以查看出selinux的状态.sestatus -v ...

  9. VB6.0快捷键大全(转)

    窗体设置,控件布局时用: alt+v+x可以快速显示出工具框 Alt+P+N 引用 ctrl+左右键头可以移动控件 shift+左右键头调整控件大小 F7   切换到编辑窗口 Shift+f7 切换代 ...

  10. QT Sleep(最佳的平衡:一边发送消息,一边睡眠)

    转自:http://xiangjie88.iteye.com/blog/898417 sleep()//秒msleep()//毫秒usleep()//微秒以前为了模拟鼠标点击用过这些函数,可以让进程中 ...