全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4470
推到 Plurk!
推到 Facebook!

以TADOQuery代替TClientDataSet实做3-Tier系统

 
mustapha.wang
資深會員


發表:89
回覆:409
積分:274
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-05-29 11:13:15 IP:218.1.xxx.xxx 未訂閱
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;
發表人 - mustapha.wang 於 2003/05/29 11:20:44
------
江上何人初见月,江月何年初照人
mustapha.wang
資深會員


發表:89
回覆:409
積分:274
註冊:2002-03-13

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-06-18 17:26:15 IP:218.1.xxx.xxx 未訂閱
ADO.NET的DataSet提供了GetChanges函数,可以只获得异动的资料了。 =============== 久病成良医-多试
------
江上何人初见月,江月何年初照人
hsgrass
一般會員


發表:1
回覆:8
積分:6
註冊:2007-05-10

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-05-29 15:54:27 IP:61.144.xxx.xxx 訂閱
ado.net可以用在DELPHI的WIN32程式嗎?
我現在用KBM作中間層,它查詢的時候也是一個RECORD一個FIELD的複製,資料少的時候還好,上6萬的時候就感覺到慢..

系統時間:2024-04-20 9:43:24
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!