Re: CoreData: Single coordinator, multiple contexts?
Re: CoreData: Single coordinator, multiple contexts?
- Subject: Re: CoreData: Single coordinator, multiple contexts?
- From: mmalcolm crawford <email@hidden>
- Date: Sat, 30 Apr 2005 15:09:38 -0700
On Apr 30, 2005, at 7:38 AM, Paul Mix wrote:
Xcode already provides a template -- "Core Data Application"-- to
start down this path. It provides a single-window application
where the persistent store coordinator is set up and managed by an
application delegate. You could extract the part of the -
managedObjectContext method that creates the coordinator and use
it to implement a -coordinator method (as illustrated below). You
are free then to add as many managed object contexts as you wish...
Thanks for the feedback. Allow me to revise my idiom a bit further.
A better analogy for the app I was planning would possibly be a
"Library" type of app, with two types of stores: a single,
centralized "Library" of media (books, cd's, etc.) (stored within
the app bundle or an Application Support directory), and multiple
"Personnel" document files (one for each person, that could be
saved and moved anywhere by the end-user). All details specific to
each Person would be stored in the "Person" document file, but
would have references to entities defined in the centralized
"Library" database. [...]
My plan was to use an NSPersistentDocument for the "Person"
documents (one person, one file/store, one "document" types), but
was unsure how to handle the editors for the "Library" items (many
items, one file/store, multiple "document" types).
Again *if* I understand correctly what you want, then it's reasonably
straightforward.
To edit the library, you could create a "Core Data Application".
You need change the path to the data store to point wherever is
appropriate (per - (NSString *)applicationSupportFolder), and then
you could just use the single application-wide editing context the
template creates for you and reference it from as many window
controllers as you wish.
[data store] -- [p.s.c.] -- [m.o.c.] -- [window controller] (books)
(file) |---- [window controller] (CDs)
|---- [window controller] (DVDs)
The downside to this (singe context) approach that you probably
anticipated is that is gives you a single "editing context" or
scratch pad (to use the analogy here: <http://developer.apple.com/
documentation/Cocoa/Conceptual/CoreData/Articles/cdBasics.html>). If
you make edits to instances of two type of media in two separate
windows, then a 'save' commits changes in both.
The advantage to the architecture you suggested, and outlined in the
previous reply, is that you're able to keep changes discrete per
window, and save independently:
[data store] -- [p.s.c.] -- [m.o.c.] -- [window controller] (books)
(file) |----- [m.o.c.] -- [window controller] (CDs)
|----- [m.o.c.] -- [window controller] (DVDs)
A potential disadvantage here is that if there are any relationships
between books, CDs, and/or DVDs, then you may at some stage have a
situation where changes made in one window are inconsistent with
changes recently saved by another, and a user may unwittingly
overwrite those changes. Optimistic locking won't help you here
because you have a single persistence stack. This is a rather subtle
point...
For the Person documents, you can create a standard "Core Data
Document-based Application", but configure the persistence stack so
that in addition to the document's store you also use the library store:
[document file] -- [p.s.c.] -- [m.o.c.] -- [document controller]
[library] ----|
There are two places in which you need to configure the stack. The
obvious one is the aptly-named:
- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:
(NSString *)fileType error:(NSError **)error
You can override the method to add a persistent store to the
coordinator:
- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:
(NSString *)fileType error:(NSError **)error
{
if (![super configurePersistentStoreCoordinatorForURL:url
ofType:fileType error:error])
{
return NO;
}
NSPersistentStoreCoordinator *coordinator =
[[self managedObjectContext] persistentStoreCoordinator];
libraryStore =
[coordinator addPersistentStoreWithType:STORE_TYPE
configuration:nil
URL:url // path library
options:nil
error:&error];
// implementation continues...
Note, however, that this method is invoked when an *existing*
document is first opened and when a *new* document is first saved.
Clearly, then, overriding this method isn't much help for new
documents... To address this issue, you also need to override:
- (id)initWithType:(NSString *)type error:(NSError **)error;
It should add the persistent store in the same way as configure...
So: (a) It may be worth factoring this code into a separate method;
(b) In your configure... method, or the factored method, you need to
ensure that the store hasn't already been added.
- (BOOL)addLibraryStore:(NSError **)error
{
NSURL *url = // URL for your library
NSPersistentStoreCoordinator * coordinator =
[[self managedObjectContext] persistentStoreCoordinator];
id store = [coordinator persistentStoreForURL: url];
if (store == nil) {
store =
[coordinator addPersistentStoreWithType:STORE_TYPE
configuration:nil
URL:url
options:nil
error:error];
if (store == nil) {
return NO;
}
}
return YES;
}
Note that after all this, the biggest issue you face will I suspect
be creating cross-store relationships (more anon)...
mmalc
(All code typed in Mail, so usual caveats apply.)
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden