Cocoa and Objective-C: Up and Running (by me) is now available from O'Reilly.

Changes to Core Data Models and Stores

Many new Cocoa programmers are surprised to find that Core Data won't automatically change the structure of a SQLite database when the Managed Object Model changes. They expect Core Data can just generate the necessary "alter table" commands and go. In reality, it's a tricky thing to tackle.

You'll know you've run into this when your application hangs and the console output refers to "no such column."

The simplest case during development is that you start out with a basic model, and incrementally add entities and properties as you go. This is relatively easy to do with the XML store type, since it just means additional entries in the text file. The XML file is a "long" format.

SQLite, on the other hand, is "wide." That is, there's a definitive structure to the data, with column names and data types. All of the data must fit into that structure. It's not so difficult to add a new column, and Core Data could potentially do that, but what about some other cases?

Data Safety First

For example, let's say you create a property called "poeple" and Core Data automatically generates that column. Then you realize it's a typo and rename it to "people." What should the Core Data stack do?

The store file is no longer synced with the model, so it could blast the "poeple" column since there's no attribute with that name, and just add the new "people" column, but what about all of the data? Maybe that data is important, maybe it isn't, but Core Data has no way of knowing that.

More importantly, what happens if you ship a 1.0 version of an app with the "poeple" column, then release a 1.01 version with the corrected name? Since this is a customer's machine, you must assume the data is important. There's no action Core Data can safely take.

More Complex Examples

Adding attributes is just one simple example. What if you have a single attribute which splits into multiple attributes? For example, a "fullName" attribute becomes "firstName" and "lastName" with a transient "fullName" property binding them. There's no way for Core Data to deduce how you want this to go.

It gets even more complicated with relationships being added and removed, or the reconfiguration of relationships. If a relationship needs to be removed, where do the objects at the other end of the relationship end up? It's unlikely you just want them drifting out in space.

Solutions

It's generally easier to use the XML store type during development, since it's inherently more tolerant of minor changes. You can move to the SQLite store type for production.

Once in SQLite, migration is not dead simple, but it is doable. The Core Data versioning page has some answers, and the Core Recipes example project shows you how to do it.
Design Element
Changes to Core Data Models and Stores
Posted Nov 15, 2006 — 5 comments below




 

Simon — Nov 15, 06 2413

ComicBookLover uses CoreData and I've had to write code to migrate SQLite data stores. It's not difficult, but it's something that has to be very well tested before release! (Touchwood :)

Developers should also think about aggregating new features which affect the data model, into one release. Users probably don't want to have their data migrated with every update.

Jeroen Leenarts — Nov 15, 06 2414

@Simon

I don't think a user cares one bit about data migration. If it works, they are happy. If it fails, they are unhappy. ;)

Marcus S. Zarra — Nov 16, 06 2415

There is also some sample production code available on the Core Data wiki:

http://opensource.bleepsoft.com/index.php/Main/CoreData

mmalc — Nov 16, 06 2416

The Core Data Programming Guide is quite explicit about this:

Versioning

"Core Data stores are conceptually bound to the managed object model used to create them: since a model describes the structure of the data, changing a model will render it incompatible with (and so unable to open) the stores it previously created. If you change your schema, you therefore need to migrate the data in existing stores to new version."


To further clarify, though:

Since a model describes the structure of the data in a persistent store, changing any parts of a model that alters the schema renders it incompatible with (and so unable to open) the stores it previously created. If you change your schema, you therefore need to migrate the data in existing stores to new version (see Versioning). For example, if you add a new entity or a new attribute to an existing entity, you will not be able to open old stores; if you add a validation constraint or set a new default value for an attribute, you will be able to open old stores.



The simplest case during development is that you start out with a basic model, and incrementally add entities and properties as you go. This is relatively easy to do with the XML store type, since it just means additional entries in the text file.

Although this may be the case at the moment, given the statement above there is no guarantee it will always be true [that you can add to a schema and still read an old XML store].

Scott Stevenson — Nov 16, 06 2418 Scotty the Leopard

guarantee it will always be true [that you can add to a schema and still read an old XML store]

True, I meant it in the sense it's a cheap tactic for the moment, but you're right -- it's important to not rely on that feature.




 

Comments Temporarily Disabled

I had to temporarily disable comments due to spam. I'll re-enable them soon.




Technorati Profile
Copyright © Scott Stevenson 2004-2008