I don't understand "propagates primary key"

From EOFWiki
Jump to navigationJump to search

What it really does, technically

When an object is inserted (not fetched) into an EOEditingContext, the destination of the "propagates primary key" relationship will be created on the spot and linked to the object by this relationship.

What's it good for

This is lengthy quote from an email to com.omnigroup.webobjects-dev by Richard Sinovec (Feb 6, 2001) :


"Propagate Primary Key" is a rather special option, which really only has limited applications. One use is in many-to-many intersect tables. Another use is to join two objects that exist in a to-one relationship in which one object "owns" the other - i.e., the subordinate object cannot exist without its owner, and once created, the subordinate object may never change owners.

This second usage is usually employed for performance reasons. For example, in the Movies database, the Talent and TalentPhoto objects are linked by a Prop-PK relationship. The main reason for doing this is to split the photo - which may be a rather large blob of data - out of the talent object. This allows Talent objects to be instantiating without requiring that the associated photographs be loaded into memory from the database. In standard EOF usage, it doesn't make sense to try and instantiate "partial objects"; when EOF loads an object from the database, it loads all attributes in that object. So, when we want to display a popup list containing the names of all our Talent, we need to instantiate all our Talent objects from the database. If the photo were stored as an attribute in the Talent table, then all the photographs would also have to be loaded in order to display this list of Talent. Since the pictures aren't needed for this task, then this is an unnecessary (and significant) performance hit that we probably prefer to avoid. The solution is to split the photo out into a TalentPhoto object, linked by a Prop-PK/Owns Destination relationship.

Closely related to this second usage, Prop-PK can also be used to get around database limitations. For example, the standard implementation of Oracle only allows you to have one blob in a table. If you have an object that (for example) needs to store two large images, you can't map that object to a single Oracle table. Instead, you must use multiple tables, which you may link with a Prop-PK relationship. The second image is the sole attribute of the second table. The second image may then be flattened in order to make all attributes appear to reside in the same object.

These should really be the only times you want to use Propagate Primary Key. The example you mention sounds like a significantly different pattern, one that doesn't involve Prop-PK. Without knowing more about your problem domain, I can't tell you how you should model your objects, but it most likely involves normal composition and maybe inheritance, and not Prop-PK. I doubt that either type of Account "owns" the Organization. In any case, having two independent entities both propagate their PKs to a common third entity is a definite Big Time No-No, so setting your model so that both CustomerAccount and SupplierAccount propagate their PKs to Organization is definitely not right.

As for your other post, it sounds like you're confusing Inheritance and Propagate Primary Key. They have similarities, but are distinct from each other. You don't need to set Prop-PK when inheritance is involved - depending on what type of inheritance you set up, EOF "does the right thing" with your PKs. A sort of PK-propagation may be happening, but you don't explicitly use EOF's "Prop PK" option to set it up. The "Prop PK" option is used in the patterns mentioned above.

Note that using "Propagate Primary Key" typically implies that you also use "Owns Destination" (except for M2M intersect tables).

What it is no good for

You can't use it to link optional relationships. The technical reason for this is, that during a fetch, there will be a EOFault on the relationship, which would have to turn to nil if the object does not exist. This is technically not possible with EOF (currently)

What to do

Use a toMany relationship and write an accessor for toOne access.

Here is an example: <source lang="objc"> - (void) setPerson:(Person *) object {

  NSMutableArray   *array;
  
  [self willChange];
  [self willReadRelationship:_personen];
  array = [[NSMutableArray alloc] initWithObjects:object, nil];
  [_personen release];
  _personen = array;

}


- (Person *) person {

  return( [[self willReadRelationship:_personen] lastObject]);

} </source>