Базовая проблема Миграции данных: “Персистентная миграция хранилища перестала работать, недостающая исходная модель управляемого объекта”.

Фон

  • Какао Не проект Данных Ядра Документа с двумя Моделями Управляемого объекта.
  • Модель 1 остается такой же. Модель 2 изменилась, таким образом, я хочу переместить хранилище.
  • Я создал новую версию Дизайном>, Модель данных> Добавляет Образцовую Версию в XCode.
  • Различием между версиями являются единственные отношения, от которых это было изменено на одно многим.
  • Я внес свои изменения в модель, затем сохранил.
  • Я сделал новую Модель Отображения, которая имеет старую модель как источник и новую модель как место назначения.
  • Я гарантировал все Модели Отображения и Модели данных и компилируюсь, и все копируются в папку Resource моего комплекта приложений.
  • Я включил миграции путем передачи в словаре с NSMigratePersistentStoresAutomaticallyOption ключ как [NSNumber numberWithBool:YES] при добавлении Персистентного Хранилища.
  • Вместо того, чтобы объединять все модели в пакете, я указал эти две модели, которые я хочу использовать (модель 1 и новая версия модели 2) и объединил их использование modelByMergingModels:

Проблема

Независимо от того, что я делаю для миграции, я получаю сообщение об ошибке:

"Персистентная миграция хранилища перестала работать, недостающая исходная модель управляемого объекта".

Что я попробовал

  • Я убираю после каждой сборки.
  • Я попробовал различные комбинации наличия только модели, на которую я мигрирую в Ресурсах, быть скомпилированным или обоих.
  • Так как сообщение об ошибке подразумевает, что не может найти исходную модель для моей миграции, я попытался иметь каждую версию модели и в папке Resources и быть скомпилированным.
  • Я удостоверился, что не совершаю действительно основную ошибку путем переключения назад на исходную версию моей модели данных. Прекрасное выполнение приложения.
  • Я удалил Отображающуюся Модель и новую версию модели, убрал, затем воссоздал обоих.
  • Я попытался внести другое изменение в новой модели - удаление объекта вместо этого.

Я в своем конце остроумия.

Я не могу не думать, что я сделал огромную ошибку где-нибудь, что я не вижу. Какие-либо идеи?

8
задан westsider 4 March 2011 в 19:15
поделиться

2 ответа

Две возможности:

  1. Ваша исходная модель в вашем приложении не соответствует фактическому хранилищу на диске.
  2. Ваша модель отображения не соответствует вашей исходной модели.

Включите Отладку Core Data , и вы сможете увидеть хэши, которые ищет Core Data при выполнении миграции. Сравните эти хэши с тем, что есть в вашем магазине на диске, и посмотрите, совпадают ли они. Точно так же отладка должна позволить вам увидеть хэши в модели сопоставления, чтобы помочь вам согласовать все.

Если неверно выровнена только ваша модель отображения, вы можете указать ей обновить ее из источника в меню дизайна в Xcode. Если вам не хватает фактической исходной модели для вашего файла магазина на диске, вы можете посмотреть в своей системе управления версиями или попробовать использовать автоматическую миграцию, чтобы этот файл перешел в модель, которая, по вашему мнению, является источником.

Обновление 1

Местоположение для изменения исходной и целевой моделей перемещено в нижнюю часть окна редактора:

10
ответ дан 5 December 2019 в 07:58
поделиться

Вместо того, чтобы объединять все модели в пучке, я указал две модели. которые я хочу использовать (модель 1 и новую версия модели 2) и объединил их using modelByMergingModels:

Это кажется неправильным. Зачем объединять модели? Вы хотите использовать модель 2, перенося магазин с модели 1.

Из справочника класса NSManagedObjectModel

modelByMergingModels:

Создает одну модель из массива существующих моделей. модель из массива существующих моделей.

Вам не нужно делать ничего особенного/специфического с вашей исходной моделью (model 1)... просто пока она находится в вашем бандле, автоматический процесс легкой миграции обнаружит и использует ее.

Я бы предложил отказаться от модели отображения, которую вы создали в Xcode, поскольку я наблюдал ужасную производительность по сравнению с автоматическими облегченными миграциями. Ваш пробег может отличаться, мои изменения между моделями отличаются от ваших, но я не удивлюсь. Попробуйте провести некоторые временные измерения с вашей собственной моделью отображения в связке и без нее.

 /* Inferred mapping */
 NSError *error;
 NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,nil];
 NSPersistentStore *migratedStore = [persistentStoreCoordinator addPersistentStoreWithType:nil
                                                                             configuration:nil
                                                                                       URL:self.storeURL
                                                                                   options:options
                                                                                     error:&error];
 migrationWasSuccessful = (migratedStore != nil);

Вы можете проверить в своем коде, что ваша исходная модель доступна, попытавшись загрузить ее и проверить, что она не nil:

NSString *modelDirectoryPath = [[NSBundle mainBundle] pathForResource:@"YourModelName" ofType:@"momd"];
if (modelDirectoryPath == nil) return nil;
NSString *modelPath = [modelDirectoryPath stringByAppendingPathComponent:@"YourModelName"];
NSURL *modelFileURL = [NSURL fileURLWithPath:modelPath];
NSManagedObjectModel *modelOne = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelFileURL];
if (modelOne == nil) {
    NSLog(@"Woops, Xcode lost my source model");
}
else {
    [modelOne release];
}

Это предполагает, что в вашем проекте есть ресурс "YourModelName.xcdatamodeld" и "YourModelName.xcdatamodel" внутри него.


Также вы можете проверить, совместима ли эта модель с существующим до миграции постоянным хранилищем:

NSError *error;
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:self.storeURL error:&error];
if (storeMeta == nil) {
    // Unable to read store meta
    return NO;
}
BOOL isCompatible = [modelOne isConfiguration:nil compatibleWithStoreMetadata:storeMeta];

Этот код предполагает, что у вас есть метод -storeURL для указания места загрузки постоянного хранилища.

6
ответ дан 5 December 2019 в 07:58
поделиться