About Relationships
A relationship is a special type of property that defines an association between two objects of a specific type. For example, a Company class may define a relationship with an Employee class:
Company
1

*
Employee
In this case, there may be zero or more Employee objects associated with each Company object.
Caché relationships have the following characteristics:
Defining a Relationship
A relationship is defined a special type of property. There are three keywords or modifiers required for a relationship definition:
TYPE The type (class name) of the related class. This must be a persistent class.
INVERSE The name of the corresponding relationship property in the related class (the "other side" of the relationship).
CARDINALITY The cardinality of this side of the relationship. This is either ONE, MANY, PARENT, or CHILDREN.
Other property keywords such as DESCRIPTION, FINAL, REQUIRED, SQLFIELDNAME and PRIVATE are optional. Some property keywords, such as MULTIDIMENSIONAL, do not apply.
The value of CARDINALITY defines how the relationship "appears" from this side as well as whether it is an independent or dependent relationship.
For example, suppose we have a Book object that is related to MANY Chapter objects:
Book
Chapters : Chapter (MANY)
1

*
Chapter
TheBook : Book (ONE)
The relationship Book.Chapters has cardinality of MANY. Each Chapter is related to ONE Book so the Chapter.Book relationship has cardinality of ONE.
In the case of a dependent relationship, such as an Invoice object with dependent LineItem objects,
Invoice
Items : LineItem (CHILDREN)
1

*
LineItem
TheInvoice : Invoice (PARENT)
the relationship Invoice.Items has cardinality of CHILDREN because Items is a collection of children from the point of view of Invoice. LineItem.TheInvoice has cardinality of PARENT because TheInvoice refers to the parent of this LineItem.
The cardinality value of a relationship must correspond to the cardinality value of the inverse relationship as defined in the following table:
Relationship Cardinality Inverse Relationship Cardinality
ONEMANY
MANYONE
PARENTCHILDREN
CHILDRENPARENT
In the Object Architect you can define a relationship by:
  1. creating a new property,
  2. setting its type to the persistent class you wish to associate with,
  3. clicking the relationship checkbox,
  4. entering the name of the inverse property in the associated class,
  5. and, selecting the type of relationship.
When you define a relationship, the Object Architect will automatically create the inverse relationship in the associated class.
You can also define a relationship using CDL. The syntax is:
relationship <relationship> { type = <related_class>
		[ <type_parameters> ] ; INVERSE = <inverse_relationship> ;
		CARDINALITY = ONE | PARENT | MANY | CHILDREN ;
		<other property keywords> }
TYPE, INVERSE and CARDINALITY are required. <related_class> must be a persistent class. <inverse_relationship> must be the name of a relationship in <related_class> whose <related_class> is the class containing <relationship> and <inverse_relationship> is <relationship>.
For example, here is the CDL for two related classes, Company and Employee:
class Company {
	super = %Persistent;
	persistent;

	attribute Name { type = %String; }

	// a Company has MANY Employees
	relationship Employees { type = Employee; inverse = TheCompany; cardinality = MANY;}
}

class Employee {
	super = %Persistent;
	persistent;

	attribute Name { type = %String; }
	attribute Title { type = %String; }

	// an Employee has ONE Company
	relationship TheCompany { type = Company; inverse = Employees; cardinality = ONE;}
}

Dependent Relationships
A dependent relationship, defined by having cardinality of PARENT on one side and CHILDREN on the other, has the following additional characteristics:
For example, here is the CDL for two related dependent classes, Invoice and LineItem:
class Invoice {
	super = %Persistent;
	persistent;

	attribute CustomerName { type = %String; }

	// an Invoice has CHILDREN that are LineItems
	relationship Items { type = LineItem; inverse = TheInvoice; cardinality = CHILDREN;}
}

class LineItem {
	super = %Persistent;
	persistent;

	attribute Product { type = %String; }
	attribute Quantity { type = %Integer; }

	// a LineItem has a PARENT that is an Invoice
	relationship TheInvoice { type = Invoice; inverse = Items; cardinality = PARENT;}
}

In-memory Behavior of Relationships
Programmatically, relationships behave as properties. Single-valued relationships (cardinality of ONE or PARENT) behave like atomic (non-collection) reference attributes. Multi-valued relationships (cardinality of MANY or CHILDREN) are instances of the %RelationshipObject class which has a collection-like interface.
For example, you could use the Company and Employee objects defined above in the following way:

// create a new instance of Company
Set company = ##class(Company).%New()
Set company.Name = "Chiaroscuro LLC"

// create a new instance of Employee
Set emp = ##class(Employee).%New()
Set emp.Name = "Weiss,Melanie"
Set emp.Title = "CEO"

// Now associate Employee with Company
Set emp.TheCompany = company

// Save the Company (this will save emp as well)
Do company.%Save()

// Close the objects we have New'd
Do company.%Close()
Do employee.%Close()

Relationships are fully bi-directional in memory; any operation on one side is immediately visible on the other side. We could have performed the association from the other side:
Do company.Employees.Insert(emp)

Write emp.TheCompany.Name  // this will print out "Chiaroscuro LLC"
We can load relationships from disk and use them as we would any other property. When you refer to a related object from the ONE side, the related object is automatically swizzled into memory in the same way as a reference (object-valued) property.
When you refer to a related object from the MANY side, the related objects are not swizzled immediately. Instead a transient %RelationshipObject collection object is created. As soon as any methods are called on this collection, it builds a list containing the ID values of the objects within the relationship. It is only when you refer to one of the objects within this collection that the actual related object is swizzled into memory.
Here is an example that displays all Employee objects related to a specific Company:

// open an instance of Company
Set company = ##class(Company).%OpenId(id)

// iterate over the employees; print their names
Set key = ""

Do {
	Set employee = company.Employees.GetNext(.key)
	If (employee '= "") {
		Write employee.Name,!
	}
} while (key '= "")

Do company.%Close()

In this example, closing company will remove the Company object and all of its related Employee objects from memory. Note, however, that every Employee object contained in the relationship will be swizzled into memory by the time the loop completes. If you are concerned about this—perhaps there are thousands of Employee objects—then we can modify the loop to "unswizzle" the Employee objects as we go by calling the %UnSwizzleAt method:
Do {
	Set employee = company.Employees.GetNext(.key)
	If (employee '= "") {
		Write employee.Name,!
		Do company.Employees.%UnSwizzleAt(key) // remove employee from memory
	}
} while (key '= "")
Persistent Behavior of Relationships
Only single-valued relationships have a persistent state. The state of multi-valued relationships is determined in memory by methods (Execute, Fetch, Close) of the single-valued relationship. The persistent state of a single-valued relationship is the same as a simple reference. No additional structures (indices) are created automatically. However, to improve the performance of Execute, Fetch, and Close an index is recommended if the size of the extent is large (When defining a relationship, the Object Architect will ask you if you want such an index).
Relationships, when made persistent, also maintain referential integrity by enforcing constraints and invoking referential actions. When a relationship is saved, the target of its reference is checked for existence. If it does not exist an error is returned and the save operation fails. When an object is deleted and there are objects related to it, the related objects are deleted (parent/child cardinality) or the delete operation fails (one/many cardinality).
As with IDENTIFIEDBY classes, a class containing a relationship with PARENT cardinality can store instances subordinate to the parent instance. With IDENTIFIEDBY this storage structure required explicit declaration in the class' storage definition: datalocation = {%%PARENT}("someliteral"). With parent/child relationships this storage structure is provided by default. The literal subscript is the name of the relationship in the parent class. In the Invoice/LineItem example above the compiled datalocation for LineItem would be ^ooInvoiceD("Items"). Of course, this datalocation can be defined explicitly, either to make the storage independent or to simply change the literal subscript.
Relationships are affected by a deep save in much the same way as simple references. The major difference is the list of ‘terminated relationships’ that is maintained in the multi-valued relationship. Objects in that list are also ‘deep-saved’. For example, consider these actions on the Company and Employee classes as shown in the previous examples.
Set company1 = ##class(Company).%OpenId(10)
Set company2 = ##class(Company).%OpenId(12)
Set emp = company1.Employees.GetAt(1) ; Assume that there is at least one Employee related to company1
Set emp.TheCompany = company2
Set sc = customer1.%Save()
The call to %Save() will result in company1, emp, and company2 being saved. Even though company1 is no longer related to order, order will be saved because it is still referenced by the list of terminated relationships in company1. Also, company2 will be saved because it is currently related to emp.
Using Relationships with SQL
The SQL projection of a relationship depends on its cardinality value: The single-valued side (ONE or PARENT) is projected as a simple designative reference field. For example, the Employee table will have a field called TheCompany whose value is the ID of the related Company:

	// display Employees ordered by Name
	// Get company name using reference field

	SELECT ID,Name,Title,TheCompany->Name
	FROM Employee
	ORDER BY Name

The multi-valued side is not projected as a field (Multi-valued relationships are state-less on disk and SQL does not deal with in-memory objects). Instead, you must perform a simple join based on the multi-valued side's ID value and the single-valued side's reference field:

	// Display all Employees by Company

	SELECT c.Name, e.Name
	FROM Company c, Employee e
	WHERE e.TheCompany = c.ID
	ORDER By 1,2

A single-valued relationship with cardinality of ONE is projected to SQL as a FOREIGNKEY with NOACTION specified for UPDATE and DELETE.
If the cardinality of the single-valued relationship is PARENT then the table projected from the class containing the relationship is "adopted" as a child table by the table projected from the type class of the single-valued relationship.