-
Notifications
You must be signed in to change notification settings - Fork 0
Relationships
This section discusses on how to define different types of relationships between entities in a CodeModeler model:
-
inheritance
-
association
-
composition
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.
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:
Here are the generated tables in SQL Server:
Vehicle and Truck tables have a one to one relation, and the both have a primary key on the Vehicle_Id column.
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.
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:
-
You can click on “Add Relation” in the Ribbon Bar and create a relation ad-hoc, filling the missing components;
-
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);
-
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);
-
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:
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):
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.
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:
This is the SQL Server producer output:
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:
The relation was created with a dialog box like this (note the natural “Employees have many Roles” proposed phrase):
This is the SQL Server producer output:
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.
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:
The relation was created with a dialog box like this (note the natural “one Customer has one Cart” proposed phrase):
This is the SQL Server producer output (note the two symmetric foreign keys added):
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.
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:
- Introduction
- Architect Guide
- Concepts
- Using Visual Studio
- Overview
- Creating a CodeModeler Project
- Visual Environment
- Project Hierarchy
- Design Surface
- Customizing Design Surfaces
- Ribbon Bar
- Property Grid
- Member Format Expressions
- Model Grid
- Method Editor
- View Editor
- Instance Editor and Grid
- Resources Editor
- Inferred Model Viewer
- Building
- Project Physical Layout
- Source Control Support
- Generating
- Aspect Oriented Design (AOD)
- Developer Guide
- The Business Object Model (BOM)
- CodeModeler Query Language (CMQL)
- Starting Guide - Tutorial
- Upgrade From CFE