• [转载红鱼儿]kbmmw 开发点滴:kbmMW数据集流化


    kbmMW提供了QueryService,供我们在客户端象传统数据库应用一样,直接利用ClientQuery做SQL查询,以及提交,并且能够在客 户端以事务的方式提交多个数据集,应该说,QueryService为我们提供了非常好的便利,快速将两层应用转为多层应用,如果用过ASTA,就会发 现,QueryService在对两层应用的转化上,要比其实现的更完美,层次更清晰。但在实际项目中,如果考虑应用服务器对多平台的支持以及业务逻辑的 集中实现,那么仅仅使用QueryService是不够的,我们可能还要使用WebService等kbmMW提供的其他服务,这时候涉及到一个问题,如 何自己控制数据集的流化,就象QueryService一样,通过在服务端将一个Query流化,在客户端将收到的流再调入一个ClientQuery, 反之亦然。
    对此,kbmMW为我们同样提供了完美的机制,以实现用不同的格式的流在服务器及客户端间传递数据集。来看看服务器端的实现:

    在一个Service中放置一个TkbmMWUNIDACQuery,命名为q,设置好ConnectionPool及SessionName属性;
    再放置需要的kbmMWXXXStreamFormat,然后为Service增加一个方法SUM1,方法的第一个参数,定为客户端要求传递的流格式,至此,可以看下面的实现代码了。

    // Functions published by the service.
    //------------------------------------

    function TwsYH.PerformSUM1(ClientIdent:TkbmMWClientIdentity; const Args:array of Variant):Variant;
    var
     

    st:TkbmMWMemoryStream;
    begin
         // Enter code here to perform function SUM1
         q.Close;
         q.SQL.Add('Select * from T1');
         q.Open;
         st:=TkbmMWMemoryStream.Create;
         case Args[0] of
          0:q.SaveToStreamViaFormat(st,kbmMWBinaryStreamFormat1);
          1:q.SaveToStreamViaFormat(st,kbmMWJSONStreamFormat1);
          2:q.SaveToStreamViaFormat(st,kbmMWXMLStreamFormat1);
         end;
        resultStream.LoadFromStream(st);
         st.Free;
    end;
    实现很简单,设置SQL,执行查询,按客户端要求的格式生成Stream,然后写到ResultStream中。对于客户端的实现,则正好相反:

    procedure TForm6.Button5Click(Sender: TObject);
    var
      sfBin:TkbmMWBinaryStreamFormat;
      sfJSON:TKbmMWJSONStreamFormat;
      sfXML:TkbmMWXMLStreamFormat;
    begin
      sfBin:=TkbmMWBinaryStreamFormat.Create(Self);
      sfJSON:=TKbmMWJSONStreamFormat.Create(Self);
      sfXML:=TkbmMWXMLStreamFormat.Create(Self);
      try
          label1.caption:=kbmMWSimpleClient1.Request('HTTPSERVICE','kbmMW_1.0','sum1',[rgSelectStreamFormat.ItemIndex]);
    //      label1.caption:=kbmMWSimpleClient1.Request('QUERYSERVICES','1.0','sum1',[rgSelectStreamFormat.ItemIndex]);
          kbmMWClientQuery2.Close;
          case rgSelectStreamFormat.ItemIndex of
               0:kbmMWClientQuery2.LoadFromStreamViaFormat(kbmMWSimpleClient1.ResultStream,sfBin);
               1:kbmMWClientQuery2.LoadFromStreamViaFormat(kbmMWSimpleClient1.ResultStream,sfJSON);
               2:kbmMWClientQuery2.LoadFromStreamViaFormat(kbmMWSimpleClient1.ResultStream,sfXML);
          end;
      finally
          sfBin.Free;
          sfJSON.Free;
          sfXML.Free;
      end;
    end;
    在客户端,我们用SimpleClient向指定的Service发送请求,并将请求返回的的ResultStream按请求的格式,调入一个ClientQuery中。

    在做上面测试代码时,遇到一个很奇怪的问题,就是当选择BinaryStreamFormat时,ClientQuery加载流时出错,而另外两种格式正 常。向xalion请教,他的第一判断,这不是bug,因为kbmMW第一个使用的就是Bin流,为此,我们还特意把流写成文件,对比服务器与客户端生成 的文件是否不同,xalion还做了测试,把这个文件加载到一个ClientQuery中,测试无问题,而在我这里就是出错。足足浪费几个小时的时间,最 终xalion发现在我的代码里加上这句,问题得以解决:
    kbmMWBinaryStreamFormat1.sfDef:=[sfLoadDef]
    找到病因,原因就好查了,原来,当我们自己用流来操作Query时,使用的StreamFormat控件,不能被ClientQuery.TransportStreamFormat属性引用(还有ClientTransactionResolve),为什么呢?
    procedure TkbmMWCustomClientCursor.SetTransportStreamFormat(AFormat:TkbmMWCustomStreamFormat);
    begin
         if AFormat=FTransportStreamFormat then exit;
         if AFormat<>nil then
            with AFormat do
            begin
                 sfDef:=[];//这里ClientQuery把使用的StreamFormat的sfDef清空了!
                 sfDeltas:=[sfSaveDeltas];
                 sfData:=[sfLoadData];
            end;
    ClientTransactionResolve也有同样的代码,清空使用的StreamFormat的sfDef属性值。
    至此,得到一条经验:

    就是当我们自己流化Query时,不要使用其他Query的TransportStreamFormat属引用的StreamFormat!
  • 相关阅读:
    web前端开发,一种立杆见影的编程乐趣
    SqlServer按照指定顺序对字段进行排序
    快速排序
    Jetty 的工作原理以及与 Tomcat 的比较
    windows Mysql备份脚本
    PHP 扩增mysql
    MySQL Master/Slave Master/Master 机制
    读取static 中读取SRC目录下的配置文件
    [高可用性] 负载均衡,会话保持,session同步
    Spring AOP配置选项
  • 原文地址:https://www.cnblogs.com/xalion/p/2725424.html
Copyright © 2020-2023  润新知