Search code examples
iosobjective-cxcodecore-datacore-data-migration

Migration with split core data model


The project(a static library) had a single data model with entities which could actually be grouped by their concerns and put into separate data models but was not separated because necessity did not arise in the beginning when the project was designed. But now as the project has grown and we are refactoring code to modularise it, the data model had to be split into one single core data model and other models belonging to each module.The challenge now is that we are unable to figure out how to safely migrate with this scenario.

To be clear---

  • In the beginning --- The Project(with no modules) had single data model called CoreDataModel with entities, A,B,C,D.
  • Now ---------------- The Project has 1 module(a separate static library itself with main project lib as dependency) with the original CoreDataModel split into two 1) CoreDataModel with entities A,B. 2) ModuleDataModel with entities C,D.

Now to safely migrate I want the data existing in current app belonging to the original CoreDataModel(in file CoreData.sqllite) to be separately(with respect to their belonging entities) put into CoreData.sqllite and ModuleData.sqllite.


Solution

  • Reading your first sentence, I am assuming complete separation between your "CoreDataModel" and "ModuleDataModel", i.e. no relationships between (A or B) and (C or D).

    I might try to perform the migration with one or more NSEntityMigrationPolicy and a specified NSMigrationManager, using (code fragment):

    NSMigrationManager *migrationManager=[[NSMigrationManager alloc] initWithSourceModel: sourceModel destinationModel: destModel];
    BOOL success=[migrationManager migrateStoreFromURL: sourceStoreURL type: NSSQLiteStoreType options: nil withMappingModel: mappingModel toDestinationURL: destinationStoreURL destinationType: NSSQLiteStoreType destinationOptions: nil error: &migrationError];
    

    Your migration policies can override:

    - (BOOL) createDestinationInstancesForSourceInstance: (NSManagedObject*) instance entityMapping: (NSEntityMapping*) mapping manager: (NSMigrationManager*) manager error: (NSError* __autoreleasing *) error
    

    during which you can store the relevant (C, D) source entities' attributes (and entityType) in a dictionary, add this to an array and store that array in the -[NSMigrationManager userInfo] dictionary. At this stage, you would only actually be migrating A, B entities to your new store.

    Once that initial migration is complete (typically when setting up your main / "CoreData" persistentStoreCoordinator) you can retrieve the migrationManager's userInfo dictionary and store your array of dictionaries, e.g. in a property of your app delegate / core data controller.

    Once the NSManagedContexts have been initialised, "CoreData" should be properly migrated, but "ModuleData" would be empty. You can then traverse your stored array, creating new entities of C and D and setting their attributes.

    I haven't covered the extra complexity of C and D relationships, but hopefully this will be a pointer in the right direction. I did something similar when I wanted to separate a standard MOM/PSC/MOC into one MOM/MOC with two on-disk stores, managed by the same PSC. It worked fine, though seemed a little untidy, but I couldn't solve using migration policies alone. I would be interested if there are better approaches.