• 转:ADOQuery代替ClientDataSet做3Tier系统


    ADOQuery代替ClientDataSet做3-Tier系统
    2009年09月23日 星期三 11:16
    3-Tier的系统我们一般用Midas的TClientDataSet,它搭配BDE的TQuery效率还可以,毕竟是一家的;但搭配TADOQuery就慢了很多,大概9倍,因为不晓得人家的资料存储格式,只能一个Field一个Field读出来再用TDataSetProvider打包成Data:OLEVariant;
    ADO2.5提供了一个_Stream组件,配合BatchUpdate,可以做到TClientDataSet的功能,它的效率可以达到与TClientDataSet+TQuery一样:
    1.Client给SQL到Server,Server用TADOQuery获取资料,然后Save到_Stream,返回;
    2.Client用_Stream接收Server返回资料,给TADOQuery,用户可以随意增/删/改;
    3.Client把用户修改后的资料Save到_Stream,传给Server(我现在还没办法只把异动资料存到_Stream,它把没有修改的资料也Save进去了,因为在WAN上跑时资料量对效率影响大;一种方法是存为XML格式,再用XML DOM组件去解析,把没修改的资料删掉,看各位还有更好的方法没有?);
    4.Server用_Stream接收Client的修改资料,给TADOQuery,把FilterGroup设为fgPendingRecords,可以分析资料的增/删/改情况,处理企业逻辑,最后调用UpdateBatch保存资料。
    5.Client在Call Server保存成功后,也调用UpdateBatch,使资料与实际一致,因为TADOQuery没有联接Connection,因此UpdateBatch相当于TClientDataSet的ClearChangeLog
    Server端的代码(Com+):

    function TEOStudent.ReadADOData(const ASQL: WideString): OLEVariant;
    var
       AStream:_Stream;
       MS1:TMemoryStream;
       V:OLEVariant;
       P:Pointer;
    begin
       try
         ADOConnection.Close;
         ADOQuery.Close;
         ADOQuery.SQL.Text:=ASQL;
         ADOQuery.Open;
         AStream:=CoStream.Create;
         OLEVariant(ADOQuery.Recordset).Save(AStream,adPersistADTG);
         ADOQuery.Close;
         AStream.Position:=0;
         V:=AStream.Read(AStream.Size);
         MS1:=TMemoryStream.Create;
         try
           P:=VarArrayLock(V);
           try
             MS1.Size:=VarArrayHighBound(V,1)+1;
             Move(P^,MS1.Memory^,MS1.Size);
           finally
             VarArrayUnLock(V);
           end;
           Result:=VarArrayCreate([0,MS1.Size-1],varByte);
           P:=VarArrayLock(Result);
           try
             Move(MS1.Memory^,P^,MS1.Size);
           finally
             VarArrayUnLock(Result);
           end;
         finally
           MS1.Free;
         end;
         SetComplete;
       except
         SetAbort;
         Raise;
       end;
    end;

    procedure TEOStudent.SaveADOData(AData: OLEVariant);
    var
       AStream:_Stream;
       AR:_Recordset;
    begin
       try
         ADOQuery.Close;
         AStream:=CoStream.Create;
         AStream.Open(EmptyParam,adModeUnknown,adOpenStreamUnspecified, ‘‘, ‘‘);
         AStream.Type_:=adTypeBinary;
         AStream.Write(AData);
         AStream.Position:=0;
         AR:=_Recordset(CoRecordset.Create);
         AStream.Position:=0;
         AR.Open(AStream,EmptyParam,adOpenKeyset,adLockBatchOptimistic,0);
         ADOConnection.Close;
         ADOConnection.Open;
         AR.Set_ActiveConnection(ADOConnection.ConnectionObject);
         ADOQuery.Recordset:=ADOInt._Recordset(AR);
    {     ADOQuery.FilterGroup:=fgPendingRecords;
         ADOQuery.Filtered:=true;
         try
           ADOQuery.First;
           while not ADOQuery.Eof do
           begin
             case ADOQuery.UpdateStatus of
               usModified:ShowMessage(
       VarToStr(ADOQuery.FieldByName(‘SeqNo‘).OldValue)+‘:‘+
       ADOQuery.FieldByName(‘SeqNo‘).asString);
             end;
             ADOQuery.Next;
           end;
         finally
           ADOQuery.Filtered:=false; //stateless
         end;}
         ADOQuery.UpdateBatch;
         ADOConnection.Close;
         SetComplete;
       except
         SetAbort;
         Raise;
       end;
    end;

    Client端,Form上放一个TADOQuery,不用连接Connection:

    获取资料
    procedure TForm1.Button5Click(Sender: TObject);
    var
       V:OLEVariant;
       AR:_Recordset;
       AStream:_Stream;
       MS1:TMemoryStream;
       P:Pointer;
       s:string;
    begin
       DCOM.Connected:=true;
       try
         s:=‘‘;
         V:=DCOM.AppServer.ReadADOData(‘select * from FORMDD‘);
         MS1:=TMemoryStream.Create;
         try
           MS1.Size:=VarArrayHighBound(V,1)+1;
           P:=VarArrayLock(V);
           try
             Move(P^,MS1.Memory^,MS1.Size);
           finally
             VarArrayUnLock(V);
           end;
           V:=VarArrayCreate([0,MS1.Size-1],varByte);
           P:=VarArrayLock(V);
           try
             Move(MS1.Memory^,P^,MS1.Size);
           finally
             VarArrayUnLock(V);
           end;
         finally
           MS1.Free;
         end;
         AStream:=CoStream.Create;
         AStream.Open(EmptyParam,adModeUnknown,adOpenStreamUnspecified, ‘‘, ‘‘);
         AStream.Type_:=adTypeBinary;
         AStream.Write(V);

         AR:=_Recordset(CoRecordset.Create);
         AStream.Position:=0;
         AR.Open(AStream,EmptyParam,adOpenUnspecified, adLockUnspecified, -1);
         ADOQuery1.Recordset:=ADOInt._Recordset(AR);
       finally
         DCOM.Connected:=false;
       end;
    end;

    //保存资料
    procedure TForm1.Button6Click(Sender: TObject);
    var
       AStream:_Stream;
       V:OLEVariant;
    begin
       DCOM.Connected:=true;
       try
         ADOQuery1.CheckBrowseMode;
         AStream:=CoStream.Create;
         OLEVariant(ADOQuery1.Recordset).Save(AStream,adPersistADTG);
         AStream.Position:=0;
         V:=AStream.Read(AStream.Size);
         DCOM.AppServer.SaveADOData(V);
         ADOQuery1.UpdateBatch;   //no connection,means clearchangelog
       finally
         DCOM.Connected:=false;
       end;
    end;
  • 相关阅读:
    SpringMVC 配置式开发-HandlerMapping的执行流程(八)
    SpringMVC 配置式开发-BeanNameUrlHandlerMapping(七)
    SpringMVC路径问题回顾,加斜杠和不加斜杠的问题(六)
    web.xml 注册中央调度器Url-pattern 要注意的地方(五)
    SpringMVC执行流程(四)
    Spring 特点
    monkeyrunner操作多个设备的例子
    ant安装、环境变量配置及验证
    二进制、十六进制转换表
    Android源码开发利器——Java源码调试(基于4.1.2)
  • 原文地址:https://www.cnblogs.com/carcode/p/1639221.html
Copyright © 2020-2023  润新知