Search code examples
iphonedatabase-designcore-dataone-to-manydata-integrity

Maintaining integrity of Core Data Entities with many incoming one-to-many relationships


I have a Core Data store which contains a number of MediaItem entities that describe, well, media items. I also have NewsItems, which have one-to-many relationships to a number of MediaItems. So far so good.

However, I also have PlayerItems and GalleryItems which also have one-to-many relationships to MediaItems. So MediaItems are shared across entities.

Given that many entities may have one-to-many relationships, how can I set up reciprocal relationships from a MediaItem to all (1 or more) of the entities which have relationships to it and, furthermore, how can I implement rules to delete MediaItems when the number of those reciprocal relationships drops to 0?


For the record (and in case it comes in useful to somebody else), I solved this by creating an abstract MediaLinkedEntity class with a one-to-many relationship to MediaItems (named MediaItems at the MediaLinkedEntity end and LinkedEntities at the MediaItem end). I then subclassed this entity for NewsItems and GalleryItems and implemented the following -prepareForDeletion method in MediaLinkedEntity:

- (void)prepareForDeletion {

    NSSet *mediaItems = self.MediaItems;
    NSSet *linkedEntities;

    // step through all media items we link to
    for( MediaItem *mediaItem in mediaItems ){
        linkedEntities = mediaItem.LinkedEntities;
        if( [ linkedEntities count ] == 1 && [ linkedEntities containsObject: self ] ){
        // if this MediaLinkedEntity is the only entry in the mediaItem's linked entities list, delete it.
            [ mediaItem.managedObjectContext deleteObject: mediaItem ];
        }
    }   

    [ super prepareForDeletion ];
}

Essentially, following Marcus's answer below.


Solution

  • The best answer for this is to have an abstract parent entity that handles the relationship in a generic way. This will allow you to reduce the number of relationships in your model.

    As for the delete rule, you should create a subclass for "one" side of the relationships and implement their -prepareForDeletion method to check for orphaned items on the many side and then delete them when it occurs.