by Gerar » Wed, 24 May 2006 17:06:50
i,
En/na Chau Chee Yang ha escrit:
Unless you try to store detail objects in a field in the master's table
(like InstantObjects does for what it calls "parts" references), invoice
items should be stored in their own table following the mapping
described in 1, the only difference being the existence of a foreign key
(Invoice ID).
>
> 1. However, I find it difficult to use the TPersistenceBroker for
> category 2 and 3. Any ideas on how to perform the design?
>
In the framework I am working on (very experimental for now) , I have
metadata for object relations:
TOOPSRelationEndMultiplicity = (emOne, emZeroOne, emZeroMany, emOneMany);
TOOPSRelationEndAssociationType = (atAggregation, atComposition);
TOOPSRelationMetadata = class(TPersistent)
private
...
published
property End1: TOOPSRelationEndMetadata read GetEnd1 write SetEnd1;
property End2: TOOPSRelationEndMetadata read GetEnd2 write SetEnd2;
property RelationName: string read GetRelationName write
SetRelationName;
end;
TOOPSRelationEndMetadata = class(TPersistent)
private
...
public
property AssociationType: TOOPSRelationEndAssociationType read
GetAssociationType write SetAssociationType;
property Multiplicity: TOOPSRelationEndMultiplicity read
GetMultiplicity write SetMultiplicity;
published
property EndName: string read GetEndName write SetEndName;
property ReferencedObjectMetadata: TOOPSObjectMetadata read
GetReferencedObjectMetadata write SetReferencedObjectMetadata;
property RelationMetadata: TOOPSRelationMetadata read
GetRelationMetadata write SetRelationMetadata;
end;
TOOPSSimpleRelationEndMetadata = class(TOOPSRelationEndMetadata)
private
..
public
constructor Create(aKeyAttributesMetadata: Array of
TOOPSAttributeMetadata);
property LocalKeyAttributesCount: Integer read
GetLocalKeyAttributesCount;
property LocalKeyAttributesMetadata[Index: Integer]:
TOOPSSimpleAttributeMetadata read GetLocalKeyAttributesMetadata;
end;
TOOPSMultipleRelationEndMetadata = class(TOOPSRelationEndMetadata)
private
...
public
constructor Create(aKeyAttributesMetadata: Array of
TOOPSAttributeMetadata);
property ForeignKeyAttributesCount: Integer read
GetForeignKeyAttributesCount;
property ForeignKeyAttributesMetadata[Index: Integer]:
TOOPSSimpleAttributeMetadata read GetForeignKeyAttributesMetadata;
end;
Each Attribute has Metadata associated to it.
For complex attributes, like references to simple objects
(TInvoice.Customer) or to lists of objects (TInvoice.InvoiceItems), the
associated metadata has a link to a RelationEndMetadata.
When a object or object list property is accessed, it is loaded using
the relation end metadata.
The fields used for foreign keys have an attribute, but no published
property, to avoid inconsistencies, or the work to update the associated
object.
So I cannot write Invoice.CustNo := 3, because the CustNo property
doens't exist.
Instead, I write Invoice.Customer := aCustomer, and the internal foreign
key attribute (CustNo) is set to the value of the key in aCustomer,
using the Relation metadata.
Either you make Invoice.Total readonly, and in the Invoice.getTotal
getter method you just walk through it's invoice items and add the
totals and return the sum, or you keep an internal field,