3

I have a very similar code to this to duplicate a TADODataSet component and it's events.

So, If I have an ADODataSet1 I want to create a new instance ADODataSet2 as exact duplicate component of the former component.

Everything works fine, But still I'm unable to duplicate the streaming fields (ADODataSet1PollID, ADODataSet1Title, ADODataSet1Description):

object ADODataSet1: TADODataSet
  Connection = ADOConnection1
  CursorType = ctStatic
  AfterOpen = ADODataSet1AfterOpen
  CommandText = 'select top 10  * from Polls'
  Parameters = <>
  Left = 224
  Top = 40
  object ADODataSet1PollID: TGuidField
    FieldName = 'PollID'
    FixedChar = True
    Size = 38
  end
  object ADODataSet1Title: TWideStringField
    FieldName = 'Title'
    Size = 255
  end
  object ADODataSet1Description: TWideStringField
    FieldName = 'Description'
    Size = 4000
  end      
end

Another problem I'm having is that if ADODataSet1 set to Active=True, then when I call ms.ReadComponent(Dest), Active streams before Connection and that raises an Exception "Missing Connection or ConnectionString". How can I set Active to False after I write ms.WriteComponent(Source)? (A workaround is to set ADODataSet1.Active := False before duplicating it).

Note: I do not want to clone the cursor/recordset on dataset (TADODataSet.Clone) so please don't consider it as "duplicate question".

Community
  • 1
  • 1
ZigiZ
  • 2,480
  • 4
  • 25
  • 41

1 Answers1

0

Try this :

Procedure registerAllClass(CMP: TComponent);
var
  I:Integer;
begin
  if (CMP is TPersistent) then begin
    RegisterClass(TPersistentclass(cmp.ClassType));
  end;
  for I:=0 to CMP.ComponentCount-1 do
    registerAllClass(cmp.Components[i]);
end;

function DuplicateComponent(Component: TComponent): TComponent;
var
  MemStream: TMemoryStream;
  oldname:String;
begin
  oldname:=component.Name;
  try
      registerAllClass(Component);
      Component.Name:='CopyOf'+Component.Name;
      MemStream := TMemoryStream.Create;
      try
        MemStream.WriteComponent(Component);
        MemStream.Position := 0;
        result:=MemStream.ReadComponent(nil);
      finally
        MemStream.Free;
      end;
  finally
    Component.Name:=oldname;
  end;
end;

function DuplicateDataset(Dataset:TDataset):TDataset;
var
  oldActive:Boolean;
begin
  if Dataset=nil then
    result:=nil
  else begin
    oldActive:=Dataset.Active;
    try
      Dataset.Active:=false;
      result:=DuplicateComponent(Dataset) as TDataSet;
    finally
      Dataset.Active:=oldActive;
    end;
  end;  
end;
Theo
  • 454
  • 1
  • 7
  • 21
  • This does not seem to work. `Component.ComponentCount` is always 1 (`TADOCommand`). the duplicated DataSet does not have persistent fields. – ZigiZ May 12 '12 at 10:18