Skip to content

Relationships

Simon Mourier edited this page Feb 19, 2020 · 1 revision

This section discusses on how to define different types of relationships between entities in a CodeModeler model:

  • inheritance

  • association

  • composition

Relationships

Inheritance

This topic introduces how inheritance relationships are handled through CodeModeler: from how to model an inheritance relationship between two entities in a model, and what gets generated from it.

Inheritance can be set between any two standard entities (as opposed to lightweight entities). Setting up an inheritance relationship between two entities indicates to CodeModeler that the child entity inherits from the base entity. This means that the child entity will derive from the parent entity and will have the same set of properties and attributes as its parent entity plus its own properties and attributes.

Note: CodeModeler also allows to model derivation of an abstract class by a child class. This is modeled by setting the “Is Abstract” attribute (“Advanced Properties” tab) to True on the parent entity and making the child entity derive from the base abstract entity.

A common example is the relationship between the concepts Vehicle and Truck. All vehicles have common properties such as wheels, or a weight. Likewise, a truck is one particular type of vehicle: it has the same properties as the vehicle concept (i.e. wheels and a weight) but has one more particular aspect which is its size. Not all vehicles are trucks, but all trucks are vehicles. Trucks differ from other vehicles by their size property.

Here's an example on how to model such a relationship. Only the persistence layer and Business Object layer are shown in the example since all upper layers are based on those two.

Inheritance - Picture 142

To define the base entity for a specified entity using Visual Studio, you must use the “Base Entity” attribute in the Visual Studio property grid:

Inheritance - Picture 143

Database Output

Here are the generated tables in SQL Server:

Database Output - Picture 144

Vehicle and Truck tables have a one to one relation, and the both have a primary key on the Vehicle_Id column.

Business Object Model Output

The Business Object Model Producer produced the following:

  • a parent class Vehicle with the private fields _id, _weight and _wheels,

  • a child class Truck that derives from the Vehicle class and contains a private field _size.

 // Parent class : Vehicle
public class Vehicle
{
    // Fields
    private int _id;
    private int _wheels;
    private float _weight;
    protected string _typeName;
}
 
// Child class : Truck
public class Truck : Vehicle
{
    // Fields
    private float _size;
}

Note: the base class Vehicle has a protected field named _typeName to keep track of the final type name of a derived class.

Association

Entities can be related to one another to reflect relations between business concepts. For instance, a customer can have orders and orders, products.

CodeModeler supports all kinds of associations:

  • one-to-many (1:M)

  • many-to-one (M:1)

  • many-to-many (M:N)

  • one-to-one (1:1)

Relationship types do not need to be specified explicitly. From specified and types, the CodeModeler Meta Model Engine may deduce relationships and the type of relations without the need to explicitly declare them.

The CodeModeler Meta Model Engine will parse and build an in-memory meta-model out of the designed CodeModeler model. This meta-model will contain all deduced relationships, and those relationships will be interpreted by defined producers and generators to produce platform specific code.

For instance, the SQL Server Producer will create a column containing the entity key of the related entity so that junctions can be done between the two tables. Furthermore, extra load stored procedures will be generated such as LoadBy[RelatedEntityName].

In the Business Object Model (BOM), a property gets generated in the entity class. This property has the type of the related entity. The value of the property will be lazy-loaded by calling the generated LoadBy[RelatedEntityName] stored procedure:  relationships are handled at the database level, object models are mapped on the database objects and offer a simple and object oriented way to handle data.

There are multiple ways to define an association using Visual Studio:

  1. You can click on “Add Relation” in the Ribbon Bar and create a relation ad-hoc, filling the missing components;

  2. When you add a property, you can directly choose an Advanced type, and then choose a Project Type (M:1 or 1:M or 1:1) or Project Type Collection (M:1 or 1:M or N:M);

  3. In the Visual Studio property grid, change a property type and then choose Project Type (M:1 or 1:M or 1:1) or Project Type Collection (M:1 or 1:M or N:M);

  4. In the design surface, press SHIFT and drag (keeping the mouse down) a property from an entity to another property or entity (or to the same entity to create a self-relation).

Once you’ve changed the type (2 and 3) or released the mouse (4), the following dialog box appears:

Association - Picture 147

The dialog box helps you to define the relation:

  • The two entities that the relation will associate are displayed (it can be twice the same entity in a self-relation case).

  • The two properties corresponding to each side of the relation are displayed. You can change them if you want.

  • It you have named the properties carefully, with English names, respecting singular and plural in properties names, the dialog box helps you how to define the relation cardinality easily:  choose the phrase that sounds like you need

  • Then you can configure composition (cascade save and cascade delete)

If you are establishing a relation between an entity and a property, the dialog box will look more like this (note the “<Unspecified>” related property):

Association - Picture 148

In this case, you can 1) keep one side of the relation as “<Unspecified>”, or in the “Related Property” list, you can 2) choose a property, or 3) decide to create a new one.

Example 1: One to Many Relationship

This example demonstrates a one to many (1:M or M:1) relationship between a Customer entity and an Order entity. Each customer has many orders and each order is associated to one customer:

Example 1: One to Many Relationship - Picture 146

This is the SQL Server producer output:

Example 1: One to Many Relationship - Picture 149

Example 2: Many to Many Relationship

This example demonstrates how to define a many to many (M:N) relationship between a Employee entity and a Role entity. Each employee has many roles and each role is associated to many employees:

Example 2: Many to Many Relationship - Picture 150

The relation was created with a dialog box like this (note the natural “Employees have many Roles” proposed phrase):

Example 2: Many to Many Relationship - Picture 151

This is the SQL Server producer output:

Example 2: Many to Many Relationship - Picture 152

An intermediate Employee_Roles_Role_Employees table has been inferred by the CodeModeler inference engine, and then generated by the SQL Server producer. Employee and Employee_Roles_Role_Employees tables have a one to many relation, Role and Employee_Roles_Role_Employees tables have a one to many relation.

Example 3: One to One Relationship

This example demonstrates how to define a one to one relationship between a Customer entity and a ShoppingCart entity. Each Customer has one ShoppingCart and each ShoppingCart belongs to one Customer:

Example 3: One to One Relationship - Picture 153

The relation was created with a dialog box like this (note the natural “one Customer has one Cart” proposed phrase):

Example 3: One to One Relationship - Picture 154

This is the SQL Server producer output (note the two symmetric foreign keys added):

Example 3: One to One Relationship - Picture 155

Composition

A composition is like the UML notion where an instance (the aggregate) is composed of several objects (the aggregated objects). Furthermore, the aggregate lifecycle and the lifecycle of its aggregated objects are linked: if the aggregate is destroyed, its composing objects are as well.

In CodeModeler, it is modeled as an association relationship, except that we must specify that the lifecycle of the aggregate and its composing objects are linked. This is done thanks to the cascade notion. For instance, a book is composed of pages. If a book is deleted, its pages should be deleted also.

Note: A cascade delete is handled in the persistence layer in the [EntityName]_Delete stored procedure of the entity and all the delete operations are done in the same transaction of the same procedure.

On the other hand, the cascade save is handled in the Business Object Model (BOM), since objects might not have been persisted yet. Therefore, the saving of composing objects and of the aggregated object are done using their distinct stored procedures in distinct transactions.

Regarding the transactional aspect, it's possible to group both saving operations into one transaction by defining a transaction rule on the save method of the aggregated object (e.g. Book) in the model.

Referential Integrity

By default, referential integrity is not enforced in target databases, for performance and ease of development reasons.

However, you can enable relationships enforcement globally by setting the “Default Persistence Enforce” attribute (“Advanced Properties” tab) at project level to True. It's also possible to enforce a specific relationship instead of the whole project. In the design surface, you must first select the relation link, and set the “Enforce” attribute to True:

Referential Integrity - Picture 145

Clone this wiki locally