Solved

TCollection of Datasets

Posted on 2006-10-24
10
793 Views
Last Modified: 2008-02-01
I am trying to create a component with a TCollection of Datasets.

My code below works, except that the collection items arn't persistant (they dont save).
And when I exit the app or close delphi I get access violations.

WOuld someone please take a look and see what the problem is.

500 BONUS Points to the person who gets it working!

Thanks

UnSYsApps



  TCopier = class;

  TDataSetItem = class(TCollectionItem)
  private
    fDataSet: TDataSet;
    procedure SetDataSet(Value: TDataSet);
  protected
    function GetDisplayName : String; override;
  public
    procedure Assign(Source: TPersistent); override;
    destructor Destroy;override;
    constructor Create(Collection: TCollection); override;
  published
    property DataSet: TDataSet read fDataSet write SetDataSet;
  end;

  TDataSets = class(TCollection)
  private
    fCopier : TCopier;
    function GetItem(Index: Integer): TDataSetItem;
    procedure SetItem(Index: Integer; Value: TDataSetItem);
  protected
    function GetOwner : TPersistent; override;
  public
    constructor Create(Copier : TCopier);
    function Add : TDataSetItem;
    function Insert(Index: Integer): TDataSetItem;
    property Items[Index: Integer]: TDataSetItem read GetItem write SetItem; default;
  end;


  TCopier = class(TSpeedButton)
  private
    { Private declarations }
    fDataSets: TDataSets;
    procedure SetDataSets(Value: TDataSets);
  protected
    { Protected declarations }
  public
    { Public declarations }
  published
    { Published declarations }
   constructor Create(AOwner: TComponent);override;
   destructor Destroy;override;
   property Datasets: TDataSets read fDataSets write SetDataSets;
  end;

procedure TDataSetItem.SetDataSet(Value: TDataSet);
begin
 if fDataSet <> Value then
  FDataSet := Value;
end;

function TDataSetItem.GetDisplayName: String;
begin
  Result := Format('Item %d',[Index]);
end;

procedure TDataSetItem.Assign(Source: TPersistent);
begin
  if Source is TDataSetItem then
   DataSet:= TDataSetItem(Source).DataSet
  else
  inherited; //raises an exception
end;

constructor TDataSetItem.Create(Collection: TCollection);
begin
 inherited Create(Collection);
 fDataSet:= TDataSet.Create(nil);
end;

destructor TDataSetItem.Destroy;
begin
 fDataSet.Free;
 inherited Destroy;
end;

constructor TDataSets.Create(Copier: TCopier);
begin
  inherited Create(TDataSetItem);
  fCopier := Copier;
end;

function TDataSets.Add: TDataSetItem;
begin
  Result := TDataSetItem(inherited Add);
end;

function TDataSets.GetItem(Index: Integer): TDataSetItem;
begin
  Result := TDataSetItem(inherited GetItem(Index));
end;

function TDataSets.GetOwner: TPersistent;
begin
  Result := fCopier;
end;

function TDataSets.Insert(Index: Integer): TDataSetItem;
begin
  Result := TDataSetItem(inherited Insert(Index));
end;

procedure TDataSets.SetItem(Index: Integer; Value: TDataSetItem);
begin
  inherited SetItem(Index, Value);
end;

procedure TCopier.SetDataSets(Value: TDataSets);
begin
 fDataSets.Assign(Value);
end;

constructor TCopier.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 fDataSets := TDataSets.Create(Self);
end;

destructor TCopier.Destroy;
begin
 fDataSets.Free;
 inherited Destroy;
end;

procedure Register;
begin
 RegisterComponents('Custom', [TCopier]);
end;

end.
0
Comment
Question by:unsysapps
  • 5
  • 4
10 Comments
 
LVL 15

Expert Comment

by:mikelittlewood
ID: 17801570
Why not base your TDataSets on a TObjectList instead.
I find them much easier to work with, and also the freeing up of objects is all done for you if you let the object list own them.
0
 
LVL 28

Expert Comment

by:2266180
ID: 17801719
that I think it's pretty easy though I am not trying it.. yet :)

replace

    property Items[Index: Integer]: TDataSetItem read GetItem write SetItem; default;
  end;

with

  published
    property Items[Index: Integer]: TDataSetItem read GetItem write SetItem; default;
  end;

;-)
0
 

Author Comment

by:unsysapps
ID: 17803621
MikeLittleWood:

SOrry, Can't do that....I need the property to be accessible via object inspector (for adding datasets)


Ciuly:

Published property "ITEMS' cannot be of type Array



Any more suggestions!




0
 
LVL 28

Expert Comment

by:2266180
ID: 17804237
well... in order to persist it, you need a publish property. at least that is what I understood. I looked at TMemo for example which also has a list of lines. if you look at it, the publcished property is of type TStrings which has no published properties but the lines are still persisted.

Ill have to do some digging to see exactly what gets persisted, but of course the help file will be the start.

I'll get back to you in a few hours hopefully with a viable solution.
0
 
LVL 28

Expert Comment

by:2266180
ID: 17807161
just got back and as first thing, tooik this for a ride to see what exactly is not happening. so I installed the component, made a test app, droped a tcopier on teh form and an adoquery and added an item to the datasets and set it to the adoquery and saved.

result:

--------
  object Copier1: TCopier
    Left = 104
    Top = 88
    Width = 23
    Height = 22
    Datasets = <
      item
        DataSet = ADOQuery1
      end>
  end
  object ADOQuery1: TADOQuery
    Parameters = <>
    Left = 240
    Top = 96
  end
------

seems to me that it is working just fine. what is it the non-persist issue you experienced?
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:unsysapps
ID: 17807975
Really, I can get the same results as you. BUT.....I get access errors when I close the app or delphi.

Just to be sure thre was nothing else cause the problem.

I created a 2nd version using the code i posted on this thread.  I still get the same thing.

Here is the new unit i created and tested.



unit Copier2;

interface

uses
  SysUtils, Classes, DB;

type

  TCopier2 = class;

  TDataSetItem = class(TCollectionItem)
  private
    fDataSet: TDataSet;
    procedure SetDataSet(Value: TDataSet);
  protected
    function GetDisplayName : String; override;
  public
    procedure Assign(Source: TPersistent); override;
    destructor Destroy;override;
    constructor Create(Collection: TCollection); override;
  published
    property DataSet: TDataSet read fDataSet write SetDataSet;
  end;

  TDataSets = class(TCollection)
  private
    fCopier : TCopier2;
    function GetItem(Index: Integer): TDataSetItem;
    procedure SetItem(Index: Integer; Value: TDataSetItem);
  protected
    function GetOwner : TPersistent; override;
  public
    constructor Create(Copier : TCopier2);
    function Add : TDataSetItem;
    function Insert(Index: Integer): TDataSetItem;
    property Items[Index: Integer]: TDataSetItem read GetItem write SetItem; default;
  end;


  TCopier2 = class(TComponent)
  private
    { Private declarations }
    fDataSets: TDataSets;
    procedure SetDataSets(Value: TDataSets);
  protected
    { Protected declarations }
  public
    { Public declarations }
  published
    { Published declarations }
   constructor Create(AOwner: TComponent);override;
   destructor Destroy;override;
   property Datasets: TDataSets read fDataSets write SetDataSets;
  end;

procedure Register;

implementation


procedure TDataSetItem.SetDataSet(Value: TDataSet);
begin
 if fDataSet <> Value then
  FDataSet := Value;
end;

function TDataSetItem.GetDisplayName: String;
begin
  Result := Format('Item %d',[Index]);
end;

procedure TDataSetItem.Assign(Source: TPersistent);
begin
  if Source is TDataSetItem then
   DataSet:= TDataSetItem(Source).DataSet
  else
  inherited; //raises an exception
end;

constructor TDataSetItem.Create(Collection: TCollection);
begin
 inherited Create(Collection);
 fDataSet:= TDataSet.Create(nil);
end;

destructor TDataSetItem.Destroy;
begin
 fDataSet.Free;
 inherited Destroy;
end;

constructor TDataSets.Create(Copier: TCopier2);
begin
  inherited Create(TDataSetItem);
  fCopier := Copier;
end;

function TDataSets.Add: TDataSetItem;
begin
  Result := TDataSetItem(inherited Add);
end;

function TDataSets.GetItem(Index: Integer): TDataSetItem;
begin
  Result := TDataSetItem(inherited GetItem(Index));
end;

function TDataSets.GetOwner: TPersistent;
begin
  Result := fCopier;
end;

function TDataSets.Insert(Index: Integer): TDataSetItem;
begin
  Result := TDataSetItem(inherited Insert(Index));
end;

procedure TDataSets.SetItem(Index: Integer; Value: TDataSetItem);
begin
  inherited SetItem(Index, Value);
end;

procedure TCopier2.SetDataSets(Value: TDataSets);
begin
 fDataSets.Assign(Value);
end;

constructor TCopier2.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 fDataSets := TDataSets.Create(Self);
end;

destructor TCopier2.Destroy;
begin
 fDataSets.Free;
 inherited Destroy;
end;

procedure Register;
begin
 RegisterComponents('Custom', [TCopier2]);
end;

end.



I will post the code on DelphiPages as well and see what experts there get for issues

0
 

Author Comment

by:unsysapps
ID: 17808164
Try this.

Create a new application. (NOt the one you currently tested it with) and drop a component on the form. Then a drop a  TDataset (Table, query, etc) on the form. Next, add a Datatset to the components Datasets property.


Do not save!

run the application

then close the app.


SHane
0
 
LVL 28

Accepted Solution

by:
2266180 earned 500 total points
ID: 17810000
I've done exactly as you said:

started delphi (new and unsaved application already open)
added a tcopier
added a TTable (bde, yesterady i as using adoquery)
click on the ... datasets, added a new dataset, set it to ttable
f9
alt+f4
alt+f, l (aka close all from delphi)
alt+f, x (aka close delphi)

no error whatsoever

hint: create a new package. make sure you have unique name for both package and unit (add some numbers in just for the fun of it). re-test. still issues?

I am betting my money on me having a clean machine in respect to "copier" and in your case there could be some colliding somewhere. maybe an old component with the same name, almost same functionality on the path? who knows.
0
 

Author Comment

by:unsysapps
ID: 17815074
Nope, I done it on two separate machines.... one mine, one a coworkers...and get the same exact results...

0
 

Author Comment

by:unsysapps
ID: 17815083
I had to go to a TStringList instead, so im closing this question. Since you (Ciuly) have been so persistant in helping me, i will award 500 points to you

Thanks for your help!

0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
How to convert wav to mp3 in delphi 9 174
calling Tcolordialog in dll make the form disappear 8 103
Delphi: Connect to running MS Outlook 4 49
DBGrid or StringGrid ? 6 71
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Both in life and business – not all partnerships are created equal. As the demand for cloud services increases, so do the number of self-proclaimed cloud partners. Asking the right questions up front in the partnership, will enable both parties …
As a trusted technology advisor to your customers you are likely getting the daily question of, ‘should I put this in the cloud?’ As customer demands for cloud services increases, companies will see a shift from traditional buying patterns to new…

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now