Search code examples
iphonecore-datacopyentity-relationship

Copying whole object graph - copy a relation


I have a model with 2 entities: RealEstate and Container

Containers object are already saved onto the persistent store with the following hierarchy:

Container 1
    Container 2
    Container 3
Container 4
    Container 5
        Container 6

Each container has a RealEstate owner (in a given hierarchy the realEstate is always the same) Now I would like create a copy of this hierarchy changing for each containers the owner realEstate. After some tests it seems to me that it's not a trivial problem.

This is a simplified scheme of the model:

RealEstate (entity)
-------------------
name (string attribute)
containers (relation)

Container (entity)
------------------
level (int attribute)
name (string attribute)
parent (self relation to another container)
subcontainers (relation - set of containers)
realEstate (relation)

Basically each containers has a subcontainers relation with self, and a parent relation so for example Container 1 has no parent but subcontainers=[container 2, container 3] etc...

I have 2 questions:

  • if I want to copy a single attribute (NSNumber) should I copy the attribute before assign it to the copied container with something like [newContainer setLevel:[[container level] copy]] because NSNumber is actually a pointer, or it's ok to assign [newContainer setLevel:[container level]] ??
  • how to copy a relation?? I cannot simply copy the subcontainers with [newContainer setSubcontainers:[container subcontainers]] !!

This is what I'm doing:

- (void)copyContainersFromRealEstate:(RealEstate *)sourceRealEstate toRealEstate:(RealEstate *)destinationRealEstate {
    // read all RealEstate Containers to copy
 NSFetchRequest *request = [[NSFetchRequest alloc] init];
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"realEstate == %@", sourceRealEstate];
 [request setPredicate:predicate];
 [request setEntity: [ NSEntityDescription entityForName:@"Container"
                 inManagedObjectContext:destinationRealEstate.managedObjectContext] ];

 NSError *error;
 NSArray *results = [destinationRealEstate.managedObjectContext executeFetchRequest:request 
                          error:&error];

 if (results == nil) {
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
      abort();
 }
 [request release];

    // *******************************************************
 // copy each caontainer changing the real estate
 Container *newContainer;
 for (Container *container in results) {
      newContainer = (Container *)[NSEntityDescription insertNewObjectForEntityForName:@"Container" 
                 inManagedObjectContext:destinationRealEstate.managedObjectContext];

      [newContainer setRealEstate:destinationRealEstate];
      [newContainer setLevel:[container level]];
      [newContainer setSubcontainers:[container subcontainers]];  // WRONG
      [newContainer setName:[container name]];
      [newContainer setParent:[container parent]];  // WRONG
 }
    // *******************************************************

}

Any help will be appreciated. Thanks


Solution

  • if I want to copy a single attribute (NSNumber) should I copy the attribute before assign it to the copied container with something like [newContainer setLevel:[[container level] copy]] because NSNumber is actually a pointer, or it's ok to assign [newContainer setLevel:[container level]] ??

    Set the value onto the new object, it will handle it even though it is a pointer because Core Data will be writing the value down into the database so it will be translating it to a primitive at some point and "break" that pointer relationship that you are concerned about.

    how to copy a relation?? I cannot simply copy the subcontainers with [newContainer setSubcontainers:[container subcontainers]] !!

    Just set the objects and Core Data will do the right thing and construct the new relationships correctly. When you pass the NSSet to the new parent object, Core Data will iterate through the objects in the set and create new relationship connections for each one of them to the new parent object.