Skip to content
Carlo Barazzetta edited this page Dec 4, 2018 · 5 revisions

Associating Objects

Persistent object relations are defined by relational attributes in the business model and can be accessed just as easy as any other attribute.

Single object relations defined by Part and Reference attributes are accessed through the corresponding object property of the class.

Multiple object references defined by Parts and References attributes are accessed through the corresponding array property and the container methods defined for the attribute.

Assignment to relational attributes

(A close study of the code in the Example below will help to clarify the points below.)

Objects created and then assigned to part/parts attributes SHOULD NOT be freed after assignment. These attributes expect the transfer to them of ownership of the objects that they are assigned. The reference counts of these objects do not change during assignment. This means that, when an object is created and assigned to a part/parts attribute, the object that was created must NOT be freed unless an exception is raised during the assignment.

Objects created and then assigned to reference/references attributes DO need to be freed after assignment. These attributes DO NOT expect the transfer of ownership to them of the objects that they are assigned. The reference count of each of these objects is incremented during assignment. This means that, when an object is created and assigned to a reference/references attribute, the object that was created must be freed at some point after the assignment to avoid a possible memory leak.

Example The following code defines a class containing the various relation types. The procedure CreateSamplePerson creates a TPerson object with a sample name and address, associates it with a company and adds some phones and colleagues to it. The procedures Show Phones and Show Friends shows a message with the caption of each of the corresponding objects associated with the person. The code assumes that a default connector has been created.

type
  TPerson = class(TInstantObject)
  {IOMETADATA stored;
    Address: Part(TAddress);
    Company: Reference(TCompany);
    Friends: References(TPerson);
    Name: String(30);
    Phones: Parts(TPhone);}
    _Address: TInstantPart;
    _Company: TInstantReference;
    _Friends: TInstantReferences;
    _Name: TInstantString;
    _Phones: TInstantParts;
  private
    function GetAddress: TAddress;
    function GetCompany: TCompany;
    function GetFriendCount: Integer;
    function GetFriends(Index: Integer): TPerson;
    function GetName: string;
    function GetPhoneCount: Integer;
    function GetPhones(Index: Integer): TPhone;
    procedure SetAddress(Value: TAddress);
    procedure SetCompany(Value: TCompany);
    procedure SetFriends(Index: Integer; Value: TPerson);
    procedure SetName(const Value: string);
    procedure SetPhones(Index: Integer; Value: TPhone);
  public
    function AddFriend(Friend: TPerson): Integer;
    function AddPhone(Phone: TPhone): Integer;
    function RemoveFriend(Friend: TPerson): Integer;
    function RemovePhone(Phone: TPhone): Integer;
    property FriendCount: Integer read GetFriendCount;
    property Friends[Index: Integer]: TPerson read GetFriends write SetFriends;
    property PhoneCount: Integer read GetPhoneCount;
    property Phones[Index: Integer]: TPhone read GetPhones write SetPhones;
  published
    property Address: TAddress read GetAddress write SetAddress;
    property Company: TCompany read GetCompany write SetCompany;
    property Name: string read GetName write SetName;
  end;

function CreateSamplePerson(Company: TCompany): TPerson;
var
  I: Integer;
  Phone: TPhone;
begin
  Result := TPerson.Create;
  try
    Result.Name := 'John Doe';
    Result.Address.Street := 'Summer Street 1';
    Result.Company := Company;

    { Add phones }
    Phone := TPhone.Create;
    try
      Phone.Name := 'Home';
      Phone.Number := '12345678';
      Result.AddPhone(Phone);
    except
      Phone.Free;
      raise;
    end;
    Phone := TPhone.Create;
    try
      Phone.Name := 'Office';
      Phone.Number := '32187654';
      Result.AddPhone(Phone);
    except
      Phone.Free;
      raise;
    end;

    { Add new Person as a Friend }
    Person := TPerson.Create;
    try
      Person.Name := 'Fred Bloggs';
      Result.AddFriend(Person);
    finally
      Person.Free;
    end;

    { Add colleagues as Friends }
    with TInstantSelector.Create(nil) do
    try
      Command.Text := 'SELECT * FROM TPerson WHERE Company = ' + Company.Id;
      Open;
      for I := 0 to Pred(ObjectCount) do
        Result.AddFriend(Objects[I] as TPerson);
    finally
      Free;
    end;

    Result.Store;
  except
    Result.Free;
    raise;
  end;
end;

procedure ShowPhones(Person: TPerson);
var
  I: Integer;
begin
  for I := 0 to Pred(Person.PhoneCount) do
    ShowMessage(Person.Phones[I].Caption);
end;

procedure ShowFriends(Person: TPerson);
var
  I: Integer;
begin
  for I := 0 to Pred(Person.FriendCount) do
    ShowMessage(Person.Friends[I].Caption);
end;

procedure DemonstrateRelations;
var
  Company: TCompany;
  Person: TPerson;
begin
  Company := TCompany.Retrieve('Happy Donuts');
  try
    Person := CreateSamplePerson(Company);
    try
      ShowPhones(Person);
      ShowFriends(Person);
    finally
      Person.Free;
    end;
  finally
    Company.Free;
  end;
end;
Clone this wiki locally