CoreData:Migrate data from bundled db
Asked Answered
M

2

1

Our app is having a coredata store which is based on a single coredata model. There are read-only data as well as read-write data.

The read-only data are pre-loaded and bundled along with the app, so that on a fresh install, this database is copied to the application sandbox and from there on the data base will be updated via webservice (ie only the changed data will get updated from webservice so that less data is transferred).

Now we have situation where we need to add more attributes to the read-only entities.

Light weight migration will help in upgrading the schema easily, but the problem is about the new data, since we are adding new attributes to all the read-only entities, all the data records are changed and a webservice sync might take a lot of time to download and update data. To avoid this we are bundling the updated data along with the app ( this will solve the issue for a fresh install). But for the users which are upgrading the app is there a standard mechanism to copy the read-only entities from the bundled db and update those to the existing database in the sandbox so that they will get the updated read-only data and also their read-write data remains intact.

UPDATE

Here is the scenario,

I have X.sqlite bundled with the proj (which has new schema), if X.sqlite is not there in doc dir I then copy it and from there everything works OK. Now in the App update scenario, X.sqilte will be already present in doc dir and won’t be copied and the migration assistant will migrate the schema. So now we have X.sqlite with the new schema in doc dir but old data (without new attributes). Now what I want to know is if there is a way to merge the data from bundled X.sqlite with the one which is there in the doc dir. I want to know if there is a process for merging.

To be more precise

Below are the entities

*Store - ReadOnly

*Products - ReadOnly

*ProductGroups - ReadOnly

*ShopList - User based

All are in the same model and in the same store.

Now Store/ Products / ProductGroups have extra attributes.

Lightweight migrator will migrate the schema of X.Sqlite so that the DB will have the new attribute columns. Now what I am concerned is the next step,

Lets take Store as an example. Store has two new attributes latitude and logitude. Now the question how to copy the data? the steps

Copying the bundled DB to doc dir with diff name? Create a new persistance co-ordinator? Read the bundled data and get the objects? then iterate through the existing db?

Marauding answered 13/11, 2015 at 13:39 Comment(1)
Guys any help would be appreciatedMarauding
M
0

Ok So finally after a lot of research I achieved my goal, below are the trails and solutions that i did

Sol 1

  1. Have the read-only and read-write data in separate databases, so that I can safely delete the readonly db if there is any master data update and I can safeguard user's data, but considering the timelines and constraints that I have, it wont be possible for me. Posting here so that it might help others.

Sol 2

I thought rather trying to merge the new data from bundled DB to the existing DB, I thought of merging the user data from existing db to the new db. Below are the steps done. --> Created a new datacontext.

--> Created a new persistent co-ordinator

--> Renamed the bundled db with _v2 and copied it to the Doc directory, now we have 2 DB in the doc dir I took some app Importing large data sets

--> Now using the ManagedObject clone category, I copied all the user info data from the existing db to the new db _v2. Found the category here NSManagedObject+Clone

--> Worked fine, now I got my _v2 database with new readonly data and the user data from the old database.

--> Now I need to give control back to the default datacontext

--> I tried to change the PSC of the old context to the new PSC but system didnt allow me to do that.

--> I then tried to change the persistence store of the old context to the new store but I got error saying that database already exists. (migratePersistentStore:toURL:options:withType:error:)

--> I ran out of ideas here.

Sol 3

I then discussed my problems with some of my other colleagues and they suggested to provide the new data in a different format and that striked. As I already mentioned, my app has logic to download new data as JSON and merge it to core data, why can I provide a JSON file with the new data, along with my app?

I collected the new response from thew webservice and created a JSON (not big just 1.5MB) and attached with app bundle, and for users that update the app, instead of core data merging I will read the JSON data locally and do the initial merging to the core data DB, there by the data base will have the new readonly data and also user data intact. After the initial merge, everything will be taken care by online sync.

Marauding answered 3/4, 2016 at 14:27 Comment(0)
I
0

If I have understood your question: you want to update read-only data during app update--while leaving read-write data that user has changed intact.

There are several ways to achieve this:

  1. Have two separate databases. One database can have the read-write data and another with read-only data. They can relate to each other using fetched properties. During update, replace or update the read-only database--while leaving the read-write one intact.
  2. Update the database using a background thread. The update code will have it's own ManagedObjectContext--but sharing the same PersistentStore. Synch the main ManagedObjectContext from the background thread using some protocol.

The second option of updating from a background thread might work well if you choose to update from your web service.

If I haven't understood your issue, please clarify.

Interpleader answered 29/1, 2016 at 22:8 Comment(1)
Thanks for the response, I have X.sqlite bundled with the proj, if X.sqlite is not there in doc dir I then copy it and from there everything works OK. Now in the App update scenario X.sqilte will be already present and won’t be copied and the migration assistant will migrate the schema. So now we have X.sqlite with the new schema but old data. Now what I want to know is if there is a way to merge the data from bundled X.sqlite with the one which is there in the doc dir. I want to know if there is a process for merging, I want to know more on your second approach.Marauding
M
0

Ok So finally after a lot of research I achieved my goal, below are the trails and solutions that i did

Sol 1

  1. Have the read-only and read-write data in separate databases, so that I can safely delete the readonly db if there is any master data update and I can safeguard user's data, but considering the timelines and constraints that I have, it wont be possible for me. Posting here so that it might help others.

Sol 2

I thought rather trying to merge the new data from bundled DB to the existing DB, I thought of merging the user data from existing db to the new db. Below are the steps done. --> Created a new datacontext.

--> Created a new persistent co-ordinator

--> Renamed the bundled db with _v2 and copied it to the Doc directory, now we have 2 DB in the doc dir I took some app Importing large data sets

--> Now using the ManagedObject clone category, I copied all the user info data from the existing db to the new db _v2. Found the category here NSManagedObject+Clone

--> Worked fine, now I got my _v2 database with new readonly data and the user data from the old database.

--> Now I need to give control back to the default datacontext

--> I tried to change the PSC of the old context to the new PSC but system didnt allow me to do that.

--> I then tried to change the persistence store of the old context to the new store but I got error saying that database already exists. (migratePersistentStore:toURL:options:withType:error:)

--> I ran out of ideas here.

Sol 3

I then discussed my problems with some of my other colleagues and they suggested to provide the new data in a different format and that striked. As I already mentioned, my app has logic to download new data as JSON and merge it to core data, why can I provide a JSON file with the new data, along with my app?

I collected the new response from thew webservice and created a JSON (not big just 1.5MB) and attached with app bundle, and for users that update the app, instead of core data merging I will read the JSON data locally and do the initial merging to the core data DB, there by the data base will have the new readonly data and also user data intact. After the initial merge, everything will be taken care by online sync.

Marauding answered 3/4, 2016 at 14:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.