简体   繁体   English

如何实现独立克隆TADODataSet?

[英]How to achieve independent cloned TADODataSet?

The scenarios is like this:场景是这样的:

We have some SQL table.我们有一些 SQL 表。 We are performing an SQL query on this table and we have results in TADOQuery object.我们正在对该表执行 SQL 查询,并且在 TADOQuery 对象中有结果。

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 independent data(at least I thought so).因此,在克隆 DataSet 之后,我的 qryClone 应该保存独立的数据(至少我是这么认为的)。 However, performing Delete on qryOryginal causes the same operation on the qryClone.但是,对 qryOryginal 执行删除会导致对 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.我知道我可以将数据存储在其他地方,也许在 TClientDataSet 中,但我想先尝试上述解决方案。

Thanks in advance for your time.在此先感谢您的时间。

You can use the recordset of a TADODataSet to clone a TADODataSet.您可以使用 TADODataSet 的记录集来克隆 TADODataSet。

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

This version works from Delphi XE.此版本适用于 Delphi XE。 ADOInt is updated with the type library definitions for MDAC 2.8 ADOInt 更新为 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.此版本必须用于 Delphi XE 之前的 Delphi 版本。 ADOR_TLB is generated from msado28.tlb. ADOR_TLB 是从 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.我更喜欢用TClientDataSet来实现,因为复制后我们可以随意编辑。

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.如果要读取或修改单个数据集而不更改数据集上的当前光标,则可以使用 Clone 方法。

Or second way, use Devexpress dxMemData .或者第二种方式,使用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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM