Skip navigation.
 
mlRe: CoreData: Single coordinator, multiple contexts?
FROM : mmalcolm crawford
DATE : Sun May 01 00:09:38 2005

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.)

Related mailsAuthorDate
mlCoreData Best Practices James Clause Apr 29, 16:49
mlRe: CoreData Best Practices John Brownlow Apr 29, 17:36
mlRe: CoreData Best Practices Scott Stevenson Apr 29, 19:07
mlRe: CoreData Best Practices John Timmer Apr 29, 22:34
mlRe: CoreData Best Practices John Timmer Apr 29, 23:28
mlRe: CoreData Best Practices Bill Bumgarner Apr 30, 00:00
mlRe: CoreData Best Practices John Timmer Apr 30, 00:29
mlRe: CoreData Best Practices Scott Ellsworth Apr 30, 00:43
mlRe: CoreData Best Practices Chris Hanson Apr 30, 00:56
mlCoreData: Single coordinator, multiple contexts? Paul Mix Apr 30, 01:03
mlRe: CoreData Best Practices John Timmer Apr 30, 01:13
mlRe: CoreData: Single coordinator, multiple contexts? Scott Stevenson Apr 30, 01:15
mlRe: CoreData Best Practices Scott Stevenson Apr 30, 01:18
mlRe: CoreData: Single coordinator, multiple contexts? mmalcolm crawford Apr 30, 01:47
mlRe: CoreData Best Practices Bill Bumgarner Apr 30, 09:49
mlRe: CoreData: Single coordinator, multiple contexts? Paul Mix Apr 30, 16:38
mlRe: CoreData: Single coordinator, multiple contexts? mmalcolm crawford May 1, 00:09