unsysapps
asked on
TCollection of Datasets
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(Va lue: TDataSet);
begin
if fDataSet <> Value then
FDataSet := Value;
end;
function TDataSetItem.GetDisplayNam e: String;
begin
Result := Format('Item %d',[Index]);
end;
procedure TDataSetItem.Assign(Source : TPersistent);
begin
if Source is TDataSetItem then
DataSet:= TDataSetItem(Source).DataS et
else
inherited; //raises an exception
end;
constructor TDataSetItem.Create(Collec tion: 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.
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(Va
begin
if fDataSet <> Value then
FDataSet := Value;
end;
function TDataSetItem.GetDisplayNam
begin
Result := Format('Item %d',[Index]);
end;
procedure TDataSetItem.Assign(Source
begin
if Source is TDataSetItem then
DataSet:= TDataSetItem(Source).DataS
else
inherited; //raises an exception
end;
constructor TDataSetItem.Create(Collec
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:
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
end;
end.
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;
;-)
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;
;-)
ASKER
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!
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!
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.
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.
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?
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?
ASKER
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(Va lue: TDataSet);
begin
if fDataSet <> Value then
FDataSet := Value;
end;
function TDataSetItem.GetDisplayNam e: String;
begin
Result := Format('Item %d',[Index]);
end;
procedure TDataSetItem.Assign(Source : TPersistent);
begin
if Source is TDataSetItem then
DataSet:= TDataSetItem(Source).DataS et
else
inherited; //raises an exception
end;
constructor TDataSetItem.Create(Collec tion: 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
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(Va
begin
if fDataSet <> Value then
FDataSet := Value;
end;
function TDataSetItem.GetDisplayNam
begin
Result := Format('Item %d',[Index]);
end;
procedure TDataSetItem.Assign(Source
begin
if Source is TDataSetItem then
DataSet:= TDataSetItem(Source).DataS
else
inherited; //raises an exception
end;
constructor TDataSetItem.Create(Collec
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
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
end;
end.
I will post the code on DelphiPages as well and see what experts there get for issues
ASKER
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
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
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Nope, I done it on two separate machines.... one mine, one a coworkers...and get the same exact results...
ASKER
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!
Thanks for your help!
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.