Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (0)


Duplicating a Database RecordFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi all versions
Category:
DB-General
Skill Level:
Scoring:
Last Update:
01/25/2003
Search Keys:
delphi delphi3000 article borland vcl code-snippet duplicating database record
Times Scored:
2
Visits:
4237
Uploader: Andrew Baylis
Company:
Reference: N/A
 
Question/Problem/Abstract:
Duplicating a database record is occasionally quite useful. I have a report based data table (using ReportBuilder) and needed to give users the ability to duplicate reports easily without having to open the report / save under a new name.
The main issue when duplicating a record is that a Dataset only maintains one cursor, so we can't copy field data directly.
The component I have written copies the source data to a temporary store. Then the Dataset can be put into Append or Insert mode and the data copied in. Two special types of field needed to be handled: BLOBs and AutoInc. AutoInc fields are maintained by the database engine and shouldn't be copied. BLOBs are handled in various ways by database engines, so I have used the top level interface provided by a TBlobField to save / load from a memorystream.
So far, I have used this with MS Access tables (under ADO), the BDE and Memory Tables with no problems.
Answer:



The core component is TFieldCopyList and is used within a program thus:

i) Navigate to the desired record
ii) Create a TFieldCopyList object
iii) Save the data using TFieldCopyList.CopyFromDataSet
iv) Append / Insert a new record, leaving the database in dsEdit/ dsInsert mode
v) Copy the saved data to the new record using  TFieldCopyList.SaveToDataSet
vi) Post to the dataset to save the changes.
vii) Cleanup by free-ing the TFieldCopyList object

{-----------------------------------------------------------------------------
Unit Name: DataCopy
Author:    Andrew Baylis
Purpose:  Holds two classes assisting in duplicating a record within a database
History:  ver 1.0
-----------------------------------------------------------------------------}


unit DataCopy;

interface

uses Classes, db, SysUtils;

type
  TFieldData = class(TObject)
  private
    FMemory: TMemoryStream; //for holding BLOB data
    FValue: Variant; //variants allow the database engine to deal with the raw data as it wishes
  public
    constructor Create;
    destructor Destroy; override;
    procedure LoadField(fld: TField);
    procedure SaveField(fld: TField);
  end;

  TFieldCopyList = class(TObject)
  private
    FDataSet: TDataSet;
    FList: array of TFieldData; //dynamic array used to save memory and allow for flexibility
  protected
    procedure Clear;
  public
    constructor Create;
    destructor Destroy; override;
    procedure CopyFromDataSet(DataSet: TDataSet);
    procedure SaveToDataSet(DataSet: TDataSet);
  end;

implementation

constructor TFieldCopyList.Create;
begin
  inherited;
  FDataSet := nil;
  SetLength(FList, 0);
end;

destructor TFieldCopyList.Destroy;
begin
  Clear;
  inherited;
end;

procedure TFieldCopyList.Clear;
var
  i: Integer;
begin
  for i := 0 to Length(FList) - 1 do
    FList[i].Free;
  SetLength(Flist, 0);
end;

procedure TFieldCopyList.CopyFromDataSet(DataSet: TDataSet);
var
  i: Integer;
begin
  SetLength(Flist, Dataset.Fields.Count);
  for i := 0 to Dataset.Fields.Count - 1 do
    begin
      FList[i] := TFieldData.Create;
      FList[i].SaveField(DataSet.Fields[i]);
    end;
  FDataSet := DataSet;
end;

procedure TFieldCopyList.SaveToDataSet(DataSet: TDataSet);
var
  i: Integer;
begin
  if DataSet <> FDataSet then
    Exit; //stored data is not from the same table
  for i := 0 to Length(FList) - 1 do
    FList[i].LoadField(DataSet.Fields[i]);
end;

// A TFieldData object is created for each field in the dataset. Its purpose is to hold the data from the desired record

constructor TFieldData.Create;
begin
  inherited;
  FMemory := TMemoryStream.Create; //holds contents of BLOB streams
end;

destructor TFieldData.Destroy;
begin
  FMemory.Free;
  inherited;
end;

procedure TFieldData.LoadField(fld: TField);
begin
  if fld.IsBlob then
    begin
      FMemory.Position := 0;
      TBlobField(fld).LoadFromStream(FMemory);
    end
  else
    if fld.DataType <> ftAutoInc then //don't try to copy this type of field
      fld.Value := FValue;
end;

procedure TFieldData.SaveField(fld: TField);
begin
  if fld.IsBlob then
    begin
      FMemory.Clear;
      TBlobField(fld).SaveToStream(FMemory);
    end
  else
    FValue := fld.Value;
end;

end.





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment













 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
S. Kucherov
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)