A relationship is directional: One entity is considered the source, and the other is considered the destination. The relationship belongs to the source entity, and may only be traversed from source to destination. To simulate a two-way relationship you have to create an EORelationship for each direction. Although the relationship is directional, no inverse is implied (although an inverse relationship may exist).
A relationship maintains an array of joins identifying attributes from the related entities (see the EOJoin class specification for more information). Most relationships simply relate the objects of one entity to those of another by comparing attribute values between them. Such a relationship must be defined as to-one or to-many based on how many objects of the destination match each object of the source. This is called the cardinality of the relationship. In a to-one relationship, there must be exactly one destination object for each source object; in a to-many relationship there can be any number of destination objects for each source object.
A chain of relationships across several entities can be flattened, creating a single relationship that spans them all. For example, suppose you have a relationship between movies and directors, and a relationship between directors and talent. You can traverse these relationships to create a flattened relationship going directly from movies to talent. A flattened relationship is determined to be to-many or to-one based on the relationships it spans; if all are to-one, then the flattened relationship is to-one, but if any of them is to-many the flattened relationship is to-many.
Like the other major modeling classes, EORelationship provides a user dictionary that the application can use to store application-specific information related to the relationship.
This code excerpt creates an EORelationship for the relationship described above and adds it to the EOEntity for the Movie entity:
EOEntity movieEntity;//Assume this exists.
EOEntity studioEntity;//Assume this exists.
EOAttribute studioIDAttribute;
EOAttribute movieStudioIDAttribute;
EOJoin toStudioJoin;
EORelationship toStudioRelationship;
studioIDAttribute =studioEntity.attributeNamed("studioId ");
movieStudioIDAttribute =movieEntity.attributeNamed("studioId ");
toStudioJoin =new EOJoin(movieStudioIDAttribute,studioIDAttribute);
toStudioRelationship =new EORelationship();
toStudioRelationship.setName("studio ");
movieEntity.addRelationship(toStudioRelationship);
toStudioRelationship.addJoin(toStudioJoin);
toStudioRelationship.setToMany(false);
toStudioRelationship.setJoinSemantic(EORelationship.InnerJoin);
This code first gets the attributes from the source and destination entities, and then creates an EOJoin with them. Next, a new EORelationship is created, its name is set, and it's added to movieEntity . The EOJoin is added to the relationship and the relationship is set to be to-one. Finally, in the setJoinSemantic line, InnerJoin indicates that only objects that actually have a matching destination object will be included in the result when the relationship is traversed. Creating a to-many relationship in the opposite direction merely swaps the source and destination attributes, and assigns the relationship to the EOEntity for the Studio entity:
EOJoin toMoviesJoin;
EORelationship toMoviesRelationship;
toMoviesJoin =new EOJoin(studioIDAttribute,movieStudioIDAttribute);
toMoviesRelationship =new EORelationship();
toMoviesRelationship.setName("movies ");
studioEntity.addRelationship(toMoviesRelationship);
toMoviesRelationship.addJoin(toMoviesJoin);
toMoviesRelationship.setToMany(true);
toMoviesRelationship.setJoinSemantic(EORelationship.InnerJoin);
Note that this relationship is to-many precisely because the destination attribute isn't the primary key for its entity (Movie), and therefore isn't unique with regard to that entity.
A relationship isn't restricted to only one EOJoin. It's entirely possible for a relationship to be defined based on two or more attributes in the source and destination entities. For example, consider an employees database that contains a picture of each employee identified by first and last name. you'd define the relationship by joining each of the first and last names in the Employee entity to the same attribute in the EmpPhoto attribute. A simple relationship is considered to reference all of the attributes in its joins. You can use the referencesProperty method to find out if an EORelationship references a particular attribute.
This code excerpt creates a flattened relationship from Movie to Talent:
EOEntity movieEntity;//Assume this exists.
EORelationship toDirectorsRelationship =new EORelationship();
toDirectorsRelationship.setEntity(movieEntity);
toDirectorsRelationship.setName("directors ");
toDirectorsRelationship.setDefinition:("toDirector.toTalent ");
movieEntity.addRelationship(toDirectorsRelationship);
All that's needed to establish the relationship is a data path (also called the definition) naming each component relationship connected, with the names separated by periods. Note that because the cardinality of a flattened relationship is determinable from its components, no setToMany message is required here.
A simple relationship is considered to reference all of the relationships in its definition, plus every attribute referenced by the component relationships. You can use the referencesProperty method to find out if an EORelationship references another relationship or attribute.