开发者

How to achieve independent cloned TADODataSet?

开发者 https://www.devze.com 2022-12-18 21:51 出处:网络
The scenarios is like this: We have some SQL table. We are performing an SQL query on this table and we have results in TADOQuery object.

The scenarios is like this:

We have some SQL table. We are performing an SQL query on this table and we have results in TADOQuery object.

var
  qryOryginal, qryClone: TADOQuery;

begin
  //setup all the things here
  qryOryginal.Active := True;
  qryClone.Clone(qryOryginal, ltBatchOptimistic);
  qryOryginal.Delete; //delete in qryOryginal casues that qryClone deletes its record too!
end;

So, after cloning the DataSet my qryClone should hold and indep开发者_Python百科endent data(at least I thought so). However, performing Delete on qryOryginal causes the same operation on the qryClone. I don't want that.

Any ideas?

I know I could store the data elsewhere, in TClientDataSet perhaps but I would like to try the above solution first.

Thanks in advance for your time.


You can use the recordset of a TADODataSet to clone a TADODataSet.

ds1.Recordset := CloneRecordset(ds2.Recordset);

This version works from Delphi XE. ADOInt is updated with the type library definitions for MDAC 2.8

uses ADOInt, Variants;

function CloneRecordset(const Data: _Recordset): _Recordset;

implementation    

function CloneRecordset(const Data: _Recordset): _Recordset;
var
    newRec: _Recordset;
    stm: Stream;
begin
    newRec := CoRecordset.Create as _Recordset;
    stm := CoStream.Create;
    Data.Save(stm, adPersistADTG);
    newRec.Open(stm, EmptyParam, CursorTypeEnum(adOpenUnspecified),
        LockTypeEnum(adLockUnspecified), 0);
    Result := newRec;
end;

This version must be used for versions of Delphi prior to Delphi XE. ADOR_TLB is generated from msado28.tlb.

uses ADOInt, ADOR_TLB, Variants;

function CloneRecordset(const Data: ADOInt._Recordset): ADOInt._Recordset;

implementation

function CloneRecordset(const Data: ADOInt._Recordset): ADOInt._Recordset;
var
    newRec: ADOR_TLB._Recordset;
    stm: Stream;
begin
    newRec := ADOR_TLB.CoRecordset.Create as ADOR_TLB._Recordset;
    stm := CoStream.Create;
    (Data as ADOR_TLB._Recordset).Save(stm, adPersistADTG);
    newRec.Open(stm, EmptyParam, CursorTypeEnum(adOpenUnspecified),
        LockTypeEnum(adLockUnspecified), 0);
    Result := newRec as ADOInt._Recordset;
end;


I more like realization with TClientDataSet, because we can freely edit it as we need after copying.

var
  MyADOStoredProc: TADOStoredProc;
  DataSetProvider: TDataSetProvider;
  ClientDataSet: TClientDataSet;
  DataSource: TDataSource;


    ...

    // here now we have an opened ADOStoredProc object MyADOStoredProc
    // let's copy data from it

    DataSetProvider := TDataSetProvider.Create(Self);
    DataSetProvider.Name := 'DataSetProvider' + FormatDateTime('_yyyy_mm_dd_hh_nn_ss', Now);
    DataSetProvider.DataSet := MyADOStoredProc;
    ClientDataSet := TClientDataSet.Create(Self);
    ClientDataSet.ProviderName := DataSetProvider.Name;
    DataSource := TDataSource.Create(Self);
    DataSource.DataSet := ClientDataSet;

    ClientDataSet.Open;
    MyADOStoredProc.Close;

    ClientDataSet.First;
    // here we can modify our ClientDataSet as we need, besides MyADOStoredProc is closed
    if not ClientDataSet.Eof then
      ClientDataSet.Delete;

    ...


Cloning just clones the cursor on dataset, not duplicating the data kept in the dataset.

If you need to have two independent data, then you have to copy the data from the original dataset to the second one.

If you want to read or modify a single dataset without changing the current cursor on the dataset, then you can use Clone method.


Or second way, use Devexpress dxMemData. Very useful and easy-to-use component.

var
  MD: TdxMemData;
  SP: TADOStoredProc;
...
...
  // and after opening stored procedure:
  MD.Close;
  MD.Open;
  MD.LoadFromDataset(SP);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号