Core data Migration Delete data of entity
Asked Answered
A

4

8

I want to do Lightweight migration in core-data. I am adding an attribute to an entity which is working well.

But I want after this particular migration that entity's data (all objects contained in that entity's table) to be deleted.

I gone through this question, but this method is not looking good as I wanted to keep separate the logic of each migration which will be required in future.

I gave a thought to one way that directly rename that entity but not specifying the rename Identifier so that Core data will process it as deletion of an entity and addition of a new entity, but this thing will not become permanent solution for every similar case in future migrations.

Is there any way if I can delete data directly by going through UI of xcdatamodeld or is there any other method?

Amalita answered 9/10, 2015 at 3:50 Comment(0)
S
7

I was able to do this, after much frustration of finding a way, using a custom EntityMigrationPolicy via a Mapping Model, setting the Custom Policy for the entity mapping, eg. EntityNameToEntityName, to this policy (ProductName.DeleteEntityPolicy):

// Swift 5
class DeleteEntityPolicy: NSEntityMigrationPolicy {
    override func begin(_ mapping: NSEntityMapping, with manager: NSMigrationManager) throws {
        // Get all current entities and delete them before mapping begins
        let entityName = "EntityName"
        let request = NSFetchRequest<NSManagedObject>(entityName: entityName)
        let context = manager.sourceContext
        let results = try context.fetch(request)
        results.forEach(context.delete)
        try super.begin(mapping, with: manager)
    }
}

More info of approach to set up a custom migration with a mapping model: https://stackoverflow.com/a/40662940

Would love to know if there's a better way/built in way to do this.

Summary answered 12/6, 2019 at 2:8 Comment(2)
It seems I found a more easy way to do it https://mcmap.net/q/1307098/-core-data-migration-delete-data-of-entityCarlisle
error: (8) attempt to write a readonly database CoreData: error: (8) attempt to write a readonly database error: Unhandled error from executeBatchDeleteRequest error during SQL execution : attempt to write a readonly database and userInfo { NSFilePath = ".....sqlite3"; NSSQLiteErrorDomain = 8; } For me its not workingSixpence
S
3

You can do this with a mapping model. To create a mapping model follow these steps:

Choose New File in XCode

Choose a template for your new file: Choose Core Data in the left pane, choose Mapping Model in the right pane and click on Next

Mapping Model Source Data Model: Select your old data model and click on Next

Mapping Model Target Data Model: Select your new data model and click on Next

Save As: You probably know how this works

In your mapping model you see a panel on the left side named 'ENTITY MAPPINGS'. Select the enity mapping of the entity you don't want to migrate and type a backspace to delete it.

To migrate automatically using a mapping model you have to configure the Persistent Store Coordinator with the NSMigratePersistentStoresAutomaticallyOption and NSInferMappingModelAutomaticallyOption options.

Silkweed answered 9/10, 2015 at 16:29 Comment(1)
Thanks for your suggestion ,can you please elaborate your answer?Amalita
F
0

The easy, "light-weight" solution without modifying the automatic migration is simply to determine if a migration took place (e.g. via a NSUserDefaults version string) and then delete all the entities you want gone.

If there are no relationships, consider NSBatchDeleteRequest which is really efficient. However, after app first start after migration it is also feasible to delete via the object graph: fetch all instances of the entity and loop through the result to delete each one, saving at the end or in batches.

Get back to me in the comments if you need advice on performance.

Frissell answered 9/10, 2015 at 23:4 Comment(0)
C
0

I found out a more easy way to skip the migration of a particular entity without removing mappings from the mapping model (which might lead to an invalid mapping model if there are complex relationships between entities).

The idea is a migration policy that does nothing and successfully validates the migration step:

Swift:

import CoreData

final class DeleteEntityMigrationPolicy: NSEntityMigrationPolicy {
    override func createDestinationInstances(forSource sInstance: NSManagedObject,
                                             in mapping: NSEntityMapping,
                                             manager: NSMigrationManager) throws { }
    
    override func createRelationships(forDestination dInstance: NSManagedObject,
                                      in mapping: NSEntityMapping,
                                      manager: NSMigrationManager) throws { }
    
    override func performCustomValidation(forMapping mapping: NSEntityMapping,
                                          manager: NSMigrationManager) throws { }
}

Objective-C:

// DSDeleteEntityMigrationPolicy.h

#import <CoreData/CoreData.h>

@interface DSDeleteEntityMigrationPolicy : NSEntityMigrationPolicy

@end

// DSDeleteEntityMigrationPolicy.m

#import "DSDeleteEntityMigrationPolicy.h"

@implementation DSDeleteEntityMigrationPolicy

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
                                      entityMapping:(NSEntityMapping *)mapping
                                            manager:(NSMigrationManager *)manager
                                              error:(NSError *__autoreleasing  _Nullable *)error {
    return YES;
}

- (BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance
                                    entityMapping:(NSEntityMapping *)mapping
                                          manager:(NSMigrationManager *)manager
                                            error:(NSError *__autoreleasing  _Nullable *)error {
    return YES;
}

- (BOOL)performCustomValidationForEntityMapping:(NSEntityMapping *)mapping
                                        manager:(NSMigrationManager *)manager
                                          error:(NSError *__autoreleasing  _Nullable *)error {
    return YES;
}

@end

Carlisle answered 27/8, 2020 at 9:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.