Как добиться самостоятельного клонирования TADODataSet? - PullRequest
4 голосов
/ 04 февраля 2010

Сценарии такие:

У нас есть таблица SQL. Мы выполняем 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;

Итак, после клонирования DataSet мой qryClone должен хранить и независимые данные (по крайней мере, я так думал). Однако выполнение Delete для qryOryginal вызывает ту же операцию для qryClone. Я не хочу этого.

Есть идеи?

Я знаю, что могу хранить данные в другом месте, возможно, в TClientDataSet, но сначала я хотел бы попробовать вышеуказанное решение.

Заранее спасибо за ваше время.

Ответы [ 3 ]

8 голосов
/ 25 января 2011

Вы можете использовать набор записей TADODataSet для клонирования TADODataSet.

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

Эта версия работает с Delphi XE.В 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;

Эта версия должна использоваться для версий Delphi до Delphi XE.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;
0 голосов
/ 17 апреля 2018

Мне больше нравится реализация с 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;

    ...
0 голосов
/ 04 февраля 2010

Клонирование просто клонирует курсор на наборе данных, не дублируя данные, хранящиеся в наборе данных.

Если вам нужно иметь два независимых данных, вам необходимо скопировать данные из исходного набора данных во второй.

Если вы хотите прочитать или изменить один набор данных без изменения текущего курсора на наборе данных, то вы можете использовать метод Clone.

...