Skip to main content

Entity Relationships

  • 4 minutes to read

In relational databases, relationships (also called associations) created between tables are defined using foreign keys. A foreign key enforces a link between the data in two tables participating in a relationship. The ExpressEntityMapping Framework supports all three available types of table relationships (one-to-one, one-to-many, and many-to-many) and allows you to map them to entity relationships. To learn about a particular relationship type and how to declare it in entity models, jump to the corresponding section by clicking a link below.

  • One-to-Many Relationships

  • One-to-One Relationships.

  • Many-to-Many Relationships.

One-to-Many Relationships

A one-to-many relationship is the most common type of relationship. In this relationship, an entity object of type A can have many associated objects of type B, but an entity object of type B can have only one associated object of type A. For example, team members can be associated with a specific team by creating a relationship (association) between a Members collection in the Team entity object (the primary key) and a field that references a Team entity object in the Member entity object (the foreign key). As a result, each team can have multiple members.

The following code implements this example. The TTeam.FMembers and TMember.FTeam fields marked with the AssociationAttribute reference the “many” and “one” ends of the association, respectively. The FMembers field is a collection of TMember entity objects associated with a particular TTeam. This collection implements the IdxEMFCollection or IdxEMFCollection<T> interface. Note that the AggregatedAttribute applied to this field enables the cascade option for TTeam entity objects. With the option, update and delete operations applied to a TTeam entity object reflect in its TMember objects.

uses
  ..., dxEMF.Core, dxEMF.Attributes, dxEMF.Types, dxEMF.Core.Collections;
type
  TTeam = class;
  TMember = class;
  [Entity]
  [Automapping]
  TTeam = class
  strict private
    [Generator(TdxGeneratorType.Identity)]
    FId: Integer;
    FName: string;
    [Association, Aggregated]
    FMembers: IdxEMFCollection<TMember>;
  public
    constructor Create;
    property Id: Integer read FId;
    property Name: string read FName write FName;
    property Members: IdxEMFCollection<TMember> read FMembers;
  end;
  [Entity]
  [Automapping]
  TMember = class
  strict private
    FId: Integer;
    FName: string;
    [Association, Nullable]
    FTeam: TTeam;
    procedure SetTeam(AValue: TTeam);
  public
    [Generator(TdxGeneratorType.Identity)]
    property Id: Integer read FId;
    property Name: string read FName write FName;
    property Team: TTeam read FTeam write SetTeam;
  end;
// ...
implementation
// ...
constructor TTeam.Create;
begin
  inherited;
  FMembers := TdxEMFCollections.Create<TMember>(Self, 'FMembers');
end;
procedure TMember.SetTeam(AValue: TTeam);
begin
  FTeam := AValue;
  if FTeam <> nil then
    FTeam.Members.Add(Self);
end;

One-to-One Relationships

In a one-to-one relationship, an entity object of type A has one associated object of type B. Their primary keys act also as foreign keys and no separate foreign key column is required. Each entity object stores a reference (also called entity reference) to the associated object.

The following code example establishes a one-to-one relationship between a User entity and its Profile (a UserProfile entity). The TUser and TUserProfile entity classes refer to each other via the TUser.Profile and TUserProfile.User properties, which store entity references. You don’t need to mark them with the AssociationAttribute, because the ExpressEntityMapping Framework automatically establishes a relationship based on the entity references.

uses
  ..., dxEMF.Core, dxEMF.Attributes, dxEMF.Types;
type
  TUserProfile = class;
  TUser = class;
  [Entity]
  [Automapping]
  TUserProfile = class
  strict private
    [Generator(TdxGeneratorType.Identity)]
    FId: Integer;
    FName: string;
    FUser: TUser;
  public
    constructor Create;
    property Id: Integer read FId;
    property Name: string read FName write FName;
    property User: TUser read FUser write FUser;
  end;
  [Entity]
  [Automapping]
  TUser = class
  strict private
    FId: Integer;
    FName: string;
    FProfile: TUserProfile;
  public
    [Generator(TdxGeneratorType.Identity)]
    property Id: Integer read FId;
    property Name: string read FName write FName;
    property Profile: TUserProfile read FProfile write FProfile;
  end;

Many-to-Many Relationships

In a many-to many-to-many relationship, many entity objects of type A can have one or more associated objects of type B, and vice versa. This type of relationship involves defining a third entity object (mapped to a junction table), whose primary key is composed of the foreign keys from the related objects. The current version of the ExpressEntityMapping Framework allows you to create this relationship using two one-to-many relationships and a junction entity class representing the “many” end of them.