Core Data Migration Exception

  • Hello,

    I would like to play with Core Data's new Leopard migration
    tools on a
    application I've been developing over the past year.  However, the
    default migration code is throwing an exception.

    The app was created in Xcode 2 but is now an Xcode 3, Leopard-only
    project.  I mention that in case there is anything special about
    migrating older Core Data Models.  I saw something to that
    effect on
    another list but don't think that's my current issue.

    Here are the steps to reproduce the exception.  After reading the
    Versioning and Migration Programming Guide I

    1. used Xcode's Design menu to add a new model and then

    2. added an new attribute to an entity.

    3. I used the Design menu to create a Mapping Model.

    4. In the code, I modified the default Model creation method,
        -managedObjectModel, by adding

        NSMigratePersistentStoresAutomaticallyOption YES

    to the storeOptions dictionary argument of addPersistentStoreWithType

    5. I further modified the -managedObjectModel code to avoid the error

        'Can't merge models with two different entities named ...'

    I now use NSManagedModel's -initWithContentsOfUrl to create the Model
    rather than one of its more convenient model-merging class
    methods.  On
    a side issue, that was fiddly to get right and remains fragile
    -- I
    might put details in another thread.

    Finally,

    6. I used Xcode's Design menu to set the new, changed Model to
    be the
        default Model then

    7. cleaned, built and ran the app.

    The app tried valiantly to start the migration but threw:

        NSInternalInconsistencyException
        Model already contains an entity named Bike.
        (full trace below)

    I don't think there is anything special about the Bike entity
    nor was it
    the one I changed -- its likely just the first one the migration process
    encountered.

    Thanks for any guidance,

    Steve

    (Please don't include this trace in replies)

    NSInternalInconsistencyException

    Model already contains an entity named Bike.

          1
    -[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods)
    _addEntity:] (in CoreData)
          2  -[NSManagedObjectModel setEntities:] (in CoreData)
          3  -[NSManagedObjectModel copyWithZone:] (in CoreData)
          4  -[NSObject copy] (in CoreFoundation)
          5  +[NSManagedObjectModel modelByMergingModels:] (in CoreData)
          6  +[NSManagedObjectModel
    modelByMergingModels:forStoreMetadata:] (in CoreData)
          7  +[NSManagedObjectModel
    mergedModelFromBundles:forStoreMetadata:] (in CoreData)
          8  -[NSStoreMigrationPolicy
    sourceModelForStoreAtURL:metadata:error:] (in CoreData)
          9  -[NSStoreMigrationPolicy(InternalMethods)
    _gatherDataAndPerformMigration:] (in CoreData)
        10  -[NSPersistentStoreCoordinator
    addPersistentStoreWithType:configuration:URL:options:error:] (in CoreData)
        11  -[WWSalesReporting_AppDelegate
    persistentStoreCoordinator] (in WWSales)
        12  -[WWSalesReporting_AppDelegate managedObjectContext]
    (in WWSales)
        13  -[NSObject(NSKeyValueCoding) valueForKey:] (in Foundation)
        14  -[NSObject(NSKeyValueCoding) valueForKeyPath:] (in Foundation)
        15  -[NSBinder
    _valueForKeyPath:ofObject:mode:raisesForNotApplicableKeys:] (in AppKit)
        16  -[NSBinder
    valueForBinding:resolveMarkersToPlaceholders:] (in AppKit)
        17  -[NSObjectParameterBinder
    _updateObject:observedController:observedKeyPath:context:] (in AppKit)
        18  -[NSObjectParameterBinder
    _observeValueForKeyPath:ofObject:context:] (in AppKit)
        19  -[NSBinder _performConnectionEstablishedRefresh] (in AppKit)
        20  -[NSObject(NSKeyValueBindingCreation)
    bind:toObject:withKeyPath:options:] (in AppKit)
        21  -[NSNibBindingConnector establishConnection] (in AppKit)
        22  -[NSIBObjectData
    nibInstantiateWithOwner:topLevelObjects:] (in AppKit)
        23  loadNib (in AppKit)
        24  +[NSBundle(NSNibLoading)
    _loadNibFile:nameTable:withZone:ownerBundle:] (in AppKit)
        25  +[NSBundle(NSNibLoading)
    loadNibFile:externalNameTable:withZone:] (in AppKit)
        26  +[NSBundle(NSNibLoading) loadNibNamed:owner:] (in AppKit)
        27  -[WWSalesReporting_AppDelegate
    applicationDidFinishLaunching:] (in WWSales)
        28  _nsnote_callback (in Foundation)
        29  __CFXNotificationPost (in CoreFoundation)
        30  _CFXNotificationPostNotification (in CoreFoundation)
        31  -[NSNotificationCenter
    postNotificationName:object:userInfo:] (in Foundation)
        32  -[NSNotificationCenter postNotificationName:object:]
    (in Foundation)
        33  -[NSApplication _postDidFinishNotification] (in AppKit)
        34  -[NSApplication _sendFinishLaunchingNotification] (in AppKit)
        35  -[NSApplication(NSAppleEventHandling) _handleAEOpen:]
    (in AppKit)
        36  -[NSApplication(NSAppleEventHandling)
    _handleCoreEvent:withReplyEvent:] (in AppKit)
        37  -[NSAppleEventManager
    dispatchRawAppleEvent:withRawReply:handlerRefCon:] (in Foundation)
        38  _NSAppleEventManagerGenericHandler (in Foundation)
        39  aeDispatchAppleEvent(AEDesc const*, AEDesc*, unsigned
    long, unsigned char*) (in AE)
        40  dispatchEventAndSendReply(AEDesc const*, AEDesc*) (i
  • Hi Steve,

    The problem might be that your old pre-Xcode 3 model doesn't have any
    version metadata. The migration manager needs to know the versions of
    both the models in order to apply the mapping. A possible solution is
    to manually call
    migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error
    : in case the model doesn't have a version.

    - Diederik

    --
    Diederik Hoogenboom
    AIM: obviousmatter
    Twitter: obviousmatter

    Obvious Matter - DiskLibrary for Mac
    http://www.obviousmatter.com

    On 2 jan 2008, at 14:59, Steve Steinitz wrote:

    > Hello,
    >
    > I would like to play with Core Data's new Leopard migration tools on a
    > application I've been developing over the past year.  However, the
    > default migration code is throwing an exception.
    >
    > The app was created in Xcode 2 but is now an Xcode 3, Leopard-only
    > project.  I mention that in case there is anything special about
    > migrating older Core Data Models.  I saw something to that effect on
    > another list but don't think that's my current issue.
    >
    > Here are the steps to reproduce the exception.  After reading the
    > Versioning and Migration Programming Guide I
    >
    > 1. used Xcode's Design menu to add a new model and then
    >
    > 2. added an new attribute to an entity.
    >
    > 3. I used the Design menu to create a Mapping Model.
    >
    > 4. In the code, I modified the default Model creation method,
    > -managedObjectModel, by adding
    >
    > NSMigratePersistentStoresAutomaticallyOption YES
    >
    > to the storeOptions dictionary argument of addPersistentStoreWithType
    >
    > 5. I further modified the -managedObjectModel code to avoid the error
    >
    > 'Can't merge models with two different entities named ...'
    >
    > I now use NSManagedModel's -initWithContentsOfUrl to create the Model
    > rather than one of its more convenient model-merging class methods.
    > On
    > a side issue, that was fiddly to get right and remains fragile -- I
    > might put details in another thread.
    >
    > Finally,
    >
    > 6. I used Xcode's Design menu to set the new, changed Model to be the
    > default Model then
    >
    > 7. cleaned, built and ran the app.
    >
    > The app tried valiantly to start the migration but threw:
    >
    > NSInternalInconsistencyException
    > Model already contains an entity named Bike.
    > (full trace below)
    >
    > I don't think there is anything special about the Bike entity nor
    > was it
    > the one I changed -- its likely just the first one the migration
    > process
    > encountered.
    >
    > Thanks for any guidance,
    >
    > Steve
    >
    >
    >
    >
    >
    > (Please don't include this trace in replies)
    >
    > NSInternalInconsistencyException
    >
    > Model already contains an entity named Bike.
    >
    > 1  -[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods)
    > _addEntity:] (in CoreData)
    > 2  -[NSManagedObjectModel setEntities:] (in CoreData)
    > 3  -[NSManagedObjectModel copyWithZone:] (in CoreData)
    > 4  -[NSObject copy] (in CoreFoundation)
    > 5  +[NSManagedObjectModel modelByMergingModels:] (in CoreData)
    > 6  +[NSManagedObjectModel
    > modelByMergingModels:forStoreMetadata:] (in CoreData)
    > 7  +[NSManagedObjectModel
    > mergedModelFromBundles:forStoreMetadata:] (in CoreData)
    > 8  -[NSStoreMigrationPolicy
    > sourceModelForStoreAtURL:metadata:error:] (in CoreData)
    > 9  -[NSStoreMigrationPolicy(InternalMethods)
    > _gatherDataAndPerformMigration:] (in CoreData)
    > 10  -[NSPersistentStoreCoordinator
    > addPersistentStoreWithType:configuration:URL:options:error:] (in
    > CoreData)
    > 11  -[WWSalesReporting_AppDelegate persistentStoreCoordinator]
    > (in WWSales)
    > 12  -[WWSalesReporting_AppDelegate managedObjectContext] (in
    > WWSales)
    > 13  -[NSObject(NSKeyValueCoding) valueForKey:] (in Foundation)
    > 14  -[NSObject(NSKeyValueCoding) valueForKeyPath:] (in Foundation)
    > 15  -[NSBinder
    > _valueForKeyPath:ofObject:mode:raisesForNotApplicableKeys:] (in
    > AppKit)
    > 16  -[NSBinder valueForBinding:resolveMarkersToPlaceholders:] (in
    > AppKit)
    > 17  -[NSObjectParameterBinder
    > _updateObject:observedController:observedKeyPath:context:] (in AppKit)
    > 18  -[NSObjectParameterBinder
    > _observeValueForKeyPath:ofObject:context:] (in AppKit)
    > 19  -[NSBinder _performConnectionEstablishedRefresh] (in AppKit)
    > 20  -[NSObject(NSKeyValueBindingCreation)
    > bind:toObject:withKeyPath:options:] (in AppKit)
    > 21  -[NSNibBindingConnector establishConnection] (in AppKit)
    > 22  -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:]
    > (in AppKit)
    > 23  loadNib (in AppKit)
    > 24  +[NSBundle(NSNibLoading)
    > _loadNibFile:nameTable:withZone:ownerBundle:] (in AppKit)
    > 25  +[NSBundle(NSNibLoading)
    > loadNibFile:externalNameTable:withZone:] (in AppKit)
    > 26  +[NSBundle(NSNibLoading) loadNibNamed:owner:] (in AppKit)
    > 27  -[WWSalesReporting_AppDelegate
    > applicationDidFinishLaunching:] (in WWSales)
    > 28  _nsnote_callback (in Foundation)
    > 29  __CFXNotificationPost (in CoreFoundation)
    > 30  _CFXNotificationPostNotification (in CoreFoundation)
    > 31  -[NSNotificationCenter postNotificationName:object:userInfo:]
    > (in Foundation)
    > 32  -[NSNotificationCenter postNotificationName:object:] (in
    > Foundation)
    > 33  -[NSApplication _postDidFinishNotification] (in AppKit)
    > 34  -[NSApplication _sendFinishLaunchingNotification] (in AppKit)
    > 35  -[NSApplication(NSAppleEventHandling) _handleAEOpen:] (in
    > AppKit)
    > 36  -[NSApplication(NSAppleEventHandling)
    > _handleCoreEvent:withReplyEvent:] (in AppKit)
    > 37  -[NSAppleEventManager
    > dispatchRawAppleEvent:withRawReply:handlerRefCon:] (in Foundation)
    > 38  _NSAppleEventManagerGenericHandler (in Foundation)
    > 39  aeDispatchAppleEvent(AEDesc const*, AEDesc*, unsigned long,
    > unsigned char*) (in AE)
    > 40  dispatchEventAndSendReply(AEDesc const*, AEDesc*) (i
    >
  • Hello,

    On 2/1/08, Diederik Hoogenboom wrote:

    > The problem might be that your old pre-Xcode 3 model doesn't have any
    > version metadata. The migration manager needs to know the versions of
    > both the models in order to apply the mapping.

    I thought Core Data created a version hash that identified the model.
    Is that only for newer stores?

    > A possible solution is to manually call migrateStoreFromURL <snip> in case
    > the model doesn't have a version.

    Thanks Diederik.

    Can anyone confirm Diederik's supposition before I jump in with his suggestion?

    And, just to clarify, if Diederik is correct, is it the the model or the
    store that needs the metadata?  If the model, isn't that easily fixed?
    If the store, well, that's harder.

    Thanks,

    Steve

    >> I would like to play with Core Data's new Leopard migration tools on a
    >> application I've been developing over the past year.  However, the
    >> default migration code is throwing an exception.
    >>
    >> The app was created in Xcode 2 but is now an Xcode 3, Leopard-only
    >> project.  I mention that in case there is anything special about
    >> migrating older Core Data Models.  I saw something to that effect on
    >> another list but don't think that's my current issue.
    >>
    >> Here are the steps to reproduce the exception.  After reading the
    >> Versioning and Migration Programming Guide I
    >>
    >> 1. used Xcode's Design menu to add a new model and then
    >>
    >> 2. added an new attribute to an entity.
    >>
    >> 3. I used the Design menu to create a Mapping Model.
    >>
    >> 4. In the code, I modified the default Model creation method,
    >> -managedObjectModel, by adding
    >>
    >> NSMigratePersistentStoresAutomaticallyOption YES
    >>
    >> to the storeOptions dictionary argument of addPersistentStoreWithType
    >>
    >> 5. I further modified the -managedObjectModel code to avoid the error
    >>
    >> 'Can't merge models with two different entities named ...'
    >>
    >> I now use NSManagedModel's -initWithContentsOfUrl to create the Model
    >> rather than one of its more convenient model-merging class methods.
    >> On a side issue, that was fiddly to get right and remains fragile --
    >> I might put details in another thread.
    >>
    >> Finally,
    >>
    >> 6. I used Xcode's Design menu to set the new, changed Model to be the
    >> default Model then
    >>
    >> 7. cleaned, built and ran the app.
    >>
    >> The app tried valiantly to start the migration but threw:
    >>
    >> NSInternalInconsistencyException
    >> Model already contains an entity named Bike.
    >> (full trace below)
    >>
    >> I don't think there is anything special about the Bike entity nor was
    >> it the one I changed -- its likely just the first one the migration
    >> process encountered.
    >>
    >> Thanks for any guidance,
    >>
    >> Steve
  • Steve,

    As I understand it, the automatic migration mechanism looks for the
    store version information in the store's metadata (under the
    NSStoreModelVersionHashesKey key). Persistent stores created under
    Tiger (or using the 10.4 sdk) don't have this key in their metadata.
    Searching the list archives for a thread between Pierre Bernard and
    mmalc will get you some code for handling this case.

    As a side note, the automatic migration code can only find data models
    and mapping models in the app's main bundle. If you keep either in a
    framework or other bundle, you'll have to start the migration manually
    anyways (I'm not sure if this is documented anywhere)...

    barry

    On Jan 3, 2008 5:26 AM, Steve Steinitz <steinitz...> wrote:
    > Hello,
    >
    > On 2/1/08, Diederik Hoogenboom wrote:
    >
    >> The problem might be that your old pre-Xcode 3 model doesn't have any
    >> version metadata. The migration manager needs to know the versions of
    >> both the models in order to apply the mapping.
    >
    > I thought Core Data created a version hash that identified the model.
    > Is that only for newer stores?
    >
    >> A possible solution is to manually call migrateStoreFromURL <snip> in case
    >> the model doesn't have a version.
    >
    > Thanks Diederik.
    >
    > Can anyone confirm Diederik's supposition before I jump in with his suggestion?
    >
    > And, just to clarify, if Diederik is correct, is it the the model or the
    > store that needs the metadata?  If the model, isn't that easily fixed?
    > If the store, well, that's harder.
    >
    > Thanks,
    >
    > Steve
    >
    >
    >
    >
    >
    >>> I would like to play with Core Data's new Leopard migration tools on a
    >>> application I've been developing over the past year.  However, the
    >>> default migration code is throwing an exception.
    >>>
    >>> The app was created in Xcode 2 but is now an Xcode 3, Leopard-only
    >>> project.  I mention that in case there is anything special about
    >>> migrating older Core Data Models.  I saw something to that effect on
    >>> another list but don't think that's my current issue.
    >>>
    >>> Here are the steps to reproduce the exception.  After reading the
    >>> Versioning and Migration Programming Guide I
    >>>
    >>> 1. used Xcode's Design menu to add a new model and then
    >>>
    >>> 2. added an new attribute to an entity.
    >>>
    >>> 3. I used the Design menu to create a Mapping Model.
    >>>
    >>> 4. In the code, I modified the default Model creation method,
    >>> -managedObjectModel, by adding
    >>>
    >>> NSMigratePersistentStoresAutomaticallyOption YES
    >>>
    >>> to the storeOptions dictionary argument of addPersistentStoreWithType
    >>>
    >>> 5. I further modified the -managedObjectModel code to avoid the error
    >>>
    >>> 'Can't merge models with two different entities named ...'
    >>>
    >>> I now use NSManagedModel's -initWithContentsOfUrl to create the Model
    >>> rather than one of its more convenient model-merging class methods.
    >>> On a side issue, that was fiddly to get right and remains fragile --
    >>> I might put details in another thread.
    >>>
    >>> Finally,
    >>>
    >>> 6. I used Xcode's Design menu to set the new, changed Model to be the
    >>> default Model then
    >>>
    >>> 7. cleaned, built and ran the app.
    >>>
    >>> The app tried valiantly to start the migration but threw:
    >>>
    >>> NSInternalInconsistencyException
    >>> Model already contains an entity named Bike.
    >>> (full trace below)
    >>>
    >>> I don't think there is anything special about the Bike entity nor was
    >>> it the one I changed -- its likely just the first one the migration
    >>> process encountered.
    >>>
    >>> Thanks for any guidance,
    >>>
    >>> Steve

    >
  • Hello,

    Thanks to Barry Wark for your comments about Core Data' default
    migration's use of version information int the store's metadata.  I had
    a look for the conversation you mentioned between mmalc and Pierre
    Bernard but only found a reference to metadata in a thread about
    spotlight.  Anyway, I think I have a thread somewhere about the topic at
    hand so not to worry (can I use that quaint Australian phrase on a US
    list?).

    That aside, I decided to do a much simpler experiment.  I created a new
    Leopard Xcode 3 project to test the default automatic migration -- just
    to be sure I had my head around it.  It didn't go well.

    Here's what I did:

    1.  created a new Core Data Application Project, MigrationTest

    2.  added an entity, TestEntity, with one attribute to the MigrationTest
        model

    3.  built and ran MigrationTest

    4.  confirmed (using SQL Browser Lite) that the database had been created
        as expected.  Noted that the Z_METADATA table had no records.

    5.  using the Design menu, added a duplicate model, called
        MigrationTest-2 to the MigrationTest project

    6.  added an new attribute to TestEntity (to have a change to migrate)

    The next two steps, 7 and 8, are related to step 9

    7.  changed the original model's name to MigrationTest-orig

    8.  renamed the new model, MigrationTest-2, to, simply, MigrationTest

    9.  modified the -managedObjectModel method to avoid the error

            'Can't merge models with two different entities named ...'

        by calling NSManagedModel's -initWithContentsOfUrl to specifically
        load the 'MigrationTest' Model rather than calling one of its more
        convenient sisters: the four model-merging class methods.

    10. used the Design menu to create a Mapping Model.

    11. cleaned, built and ran MigrationTest

    Result:

    rather than migrating the model, it displayed five cascading alerts all
    saying:

            The file “MigrationTest.sqlâ€? could not be opened
            because it is not in the right format.

            The file might be corrupted, truncated, or in a
            different format than you expect.

    Is it bug report time or am I missing a point somewhere?

    Thanks,

    Steve
  • On Jan 8, 2008, at 5:14 AM, Steve Steinitz wrote:

    > 5.  using the Design menu, added a duplicate model, called
    > MigrationTest-2 to the MigrationTest project
    > [...]
    > Is it bug report time or am I missing a point somewhere?
    >
    So you're creating two separate model files, not a single versioned
    model file...?
    <http://developer.apple.com/documentation/Cocoa/Conceptual/CoreDataVersionin
    g/Articles/vmVersioning.html#//apple_ref/doc/uid/TP40004714-DontLinkElement
    ID_10
    >

    mmalc
  • Hello mmalc

    Thanks for your reply.

    On 8/1/08, mmalc crawford wrote:

    > So you're creating two separate model files, not a single versioned
    > model file...?

    Well spotted -- yes.  I tried it both ways.  The procedure I presented
    uses two separate model files in an attempt to remove versioning from
    the equations, in case it was causing problems.  I get the same results
    with versioned models.

    <http://developer.apple.com/documentation/Cocoa/Conceptual/
    CoreDataVersioning/Articles/vmVersioning.html#//apple_ref/doc/uid/
    TP40004714-DontLinkElementID_10
    >

    Yes.  I poured over that document.  It seems to indicate that even in
    the absence of versioning Core Data will look for an appropriate source
    model -- apparently it uses a hash, as you would well know.

    Thanks again for any advice,

    Steve
previous month january 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today