Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data store atomicity with multiple stores

Core Data allows you to add multiple persistent stores to a single NSPersistentStoreCoordinator (each with a different configuration) name, thereby bringing them together in a single NSManagedObjectContext. What I haven't been able to find out is how Core Data handles atomicity of a save operation for multiple stores.

Let's say I have two stores:

NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] init];
[coordinator addPersistentStoreWithType:type configuration:@"A" URL:aURL options:nil error:NULL];
[coordinator addPersistentStoreWithType:type configuration:@"B" URL:bURL options:nil error:NULL];

NSManagedObjectContext *context = [[NSManageObjectContext alloc] init];
[context setPersistentStoreCoordinator:coordinator];

And then it's time to save I do that:

NSError *error = nil;
BOOL result = [context save:&error];

The documentation states that the sequence of events will be:

  1. Save store A
  2. Save store B

What if store A saves correctly, but store B cannot save for some reason? (e.g. the file on disk was deleted, or permissions made it read-only, that sort of thing). I cannot find any documentation detailing whether or not Core Data will then rollback the changes to store A.

It seems odd to me that the object graph would be left in an inconsistent state (i.e. one store updated, one not), but somewhat tricky and resource intensive to perform fully atomic saving across multiple stores. Would just really like some clarification here, perhaps from someone with more experience of the system!

like image 323
Mike Abdullah Avatar asked Jun 15 '09 05:06

Mike Abdullah


People also ask

Can we have multiple managed object context in Core Data?

Most apps need just a single managed object context. The default configuration in most Core Data apps is a single managed object context associated with the main queue. Multiple managed object contexts make your apps harder to debug; it's not something you'd use in every app, in every situation.

What types of stores does Core Data support?

Core Data provides four store types—SQLite, Binary, XML, and In-Memory (the XML store is not available on iOS); these are described in Persistent Store Features.

What is persistent store in Core Data?

A persistent store is a repository in which managed objects may be stored. You can think of a persistent store as a database data file where individual records each hold the last-saved values of a managed object. Core Data offers three native file types for a persistent store: binary, XML, and SQLite.

Where does Core Data store Data?

The persistent store should be located in the AppData > Library > Application Support directory.


2 Answers

I finally stumbled upon the answer today in CoreDataErrors.h. There is an error code:

    NSPersistentStoreIncompleteSaveError             = 134040, // one or more of the stores returned an error during save (stores/objects that failed will be in userInfo)

So it seems that Core Data will not attempt to roll back saves from the stores that did succeed. And indeed cannot provide atomicity across multiple stores. Fair enough!

like image 193
Mike Abdullah Avatar answered Sep 22 '22 21:09

Mike Abdullah


This sounds like something that would not be hard to get an experimental answer to by recreating your conditions - have you had time to recreate the scenario you outline?

I would do this by:

  1. creating two sqllite stores and writing a set of data to each of the files.
  2. shutdown the stores
  3. delete the second sqllite file
  4. write out an easy to see operation on the first store (might be best to do an insert into one table and delete from the other). Combine this with another operation on the second store and which should fail because of the missing file 5.Check the state of the first store.

It is my feeling that the changes to store A will not be rolled back - but I will be impressed by any other answer.

like image 21
Grouchal Avatar answered Sep 20 '22 21:09

Grouchal