Symbolic Logic:Programming:ORM Entity Relationship

Entity Relations
A foreign key relationship is an association between objects. It says there is a connection between two sets of objects. Types of connection are classified by the number of elements in each set.


 * One to One - Marriage
 * One to Many - Parent to Child
 * Many to Many - Buyers and Sellers

One To Many
A one to many relationship identifies one parent object as owning a set of child objects. Alternatively we can think of the child object having a reference to the parent object. The parent has a single Id that identifies it. The child knows this Id.

Usage
A one to many relationship is declared like.
 * class FKPet
 * FKOneToMany(class Person, symbol Pet, class Dog, symbol Owner)
 * }
 * }

This single definition does the full job of describing the association between Person and Dogs.
 * A person has a set of dogs which are pets.
 * A dog has a person who is its owner.
 * The dog knows (and records) the id of the owner.

Under the Hood
This one declaration means the same as,


 * class Person
 * // A person has a set of dogs which are pets.
 * inherit FKIsParentOf(FKPet, Dog) as Pet
 * }
 * }


 * class Dog
 * // A dog has a person who is its owner.
 * inherit FKIsChildOf(FKPet, Person) as Owner
 * }
 * }

But you dont need to explicitly declare these inheritances. FKOneToMany does this for you. This is so you dont forget one side of the relationship. The relationship is defined by the persons id being the same as the owner id on the dog. This is described by the Join method in the FKPet class.


 * class FKPet
 * public:
 * any Join(Person person, Dog dog)
 * return person.GetId == dog.GetOwnerId;
 * }
 * }
 * return person.GetId == dog.GetOwnerId;
 * }
 * }

But we dont need to write the Join method either. It is inherited from the FKOneToMany class.

Implementation
We need two special language features to define the FKOneToMany class.
 * symbol - Gives the ability to construct names.
 * Defining inheritance in another class.

In the Join function defined in the FKPet class above we needed to refer to the Owner Id of the dog. We dont want to write this method ourselves. Using symbols Get#ManySide#Id means the same as GetOwnerId if ManySide is Owner.

Symbols are also used in defining the renaming inheritance. The Dog needs GetOwner and SetOwner methods while the Person needs a GetPetList method. Renaming inheritance gives these methods to the classes.

The renaming inheritance needed by Person and Dog is defined within the FKOneToMany class.


 * class FKOneToMany(class One, symbol OneSide, class Many, symbol ManySide)
 * // Define the inheritance needed by the One and Many classes.
 * class One inherit FKIsParentOf(thisclass, Many) as OneSide
 * class Many inherit FKIsChildOf(thisclass, One) as ManySide
 * // Define the join condition.
 * any Join(One one, Many many)
 * return one.GetId == many.Get#ManySide#Id;
 * }
 * }
 * }
 * }


 * class FKIsParentOf(class relationship, class child)
 * inherit PersistBase;
 * // Get the child objects.
 * any GetList(role Time currentTime) rename as Get%List
 * if (GetMode == TemplateMode)
 * { // Construct a template for constructing COUNT, SUM, EXISTS conditions on the child.
 * return GetWhereList(x : relationship.Join(this, x)); // TODO tidy this up
 * }
 * else
 * { // Construct SQL to get the children.
 * return child.Select(x : relationship.Join(this, x), []);
 * }
 * }
 * }
 * }
 * }


 * class FKIsChildOf(class foreignKey, class Parent)
 * // The child class needs an OwnerId attribute to hold the reference to the parent.
 * inherit Attribute("Id", IdType) as %Id;
 * // Get the parent object.
 * Parent Get(role Time currentTime) rename as Get%
 * { // Construct SQL to get the parent.
 * return Parent.SelectOne(x : foreignKey.Join(x, this))
 * }
 * // Set the parent object.
 * bool Set(Parent p, role Time currentTime) rename as Get%
 * { // Set the Id on this child object to match the parent.
 * return foreignKey.Join(p, this)
 * }
 * }
 * }

One To One
The following class implemnents the One to One relationship. It is implemented as two classes referencing each other.


 * class FKOneToOne(class One, symbol OneSide, class Other, symbol OtherSide)
 * // Define the inheritance needed by the One and Many classes.
 * class One inherit FKIsChildOf(thisclass, One) as OneSide
 * class Other inherit FKIsChildOf(thisclass, Other) as OtherSide
 * // Define the join condition.
 * any Join(One one, Other other)
 * return one.GetId == other.GetId;
 * }
 * }
 * }
 * }

Many To Many
A many to many relationship needs an intermediate persistent class and table to implement the relationship. Each side has a One to Many relationship with the intermediate table.

Links

 * Symbolic Logic:Programming:Object Relational Mapping
 * Symbolic Logic:Programming:Framework
 * Symbolic Logic:Programming
 * Intelligence and Reasoning