zoukankan      html  css  js  c++  java
  • ADOQuery代替ClientDataSet做3Tier系统

    ADOQuery代替ClientDataSet做3-Tier系统
    2005-09-06 13:41:00
    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;
     
  • 相关阅读:
    storm源代码分析---Transactional spouts
    SQLServer 中存储过程
    实体添加映射
    SELECT INTO 和 INSERT INTO SELECT
    .NET System.Timers.Timer的原理和使用(开发定时执行程序)
    .net Framework 中的四种计时器
    AutoMapper 在你的项目里飞一会儿
    C#字符串、字节数组和内存流间的相互转换
    Entity Framework Code First使用者的福音 --- EF Power Tool使用记之二(问题探究)
    Entity Framework Code First使用者的福音 --- EF Power Tool使用记之一
  • 原文地址:https://www.cnblogs.com/fuyingke/p/254669.html
Copyright © 2011-2022 走看看