Основная проблема переноса данных: «Ошибка переноса хранилища, отсутствует модель управляемого объекта источника». - PullRequest
8 голосов
/ 22 марта 2010

Фон

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

Проблема

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

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

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

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

Я сошел с ума.

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

Ответы [ 5 ]

10 голосов
/ 22 марта 2010

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

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

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

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

Обновление 1

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

6 голосов
/ 01 апреля 2010

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

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

Из ссылки на класс NSManagedObjectModel

modelByMergingModels:

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

Вам не нужно делать что-то особенное / специфическое с вашей исходной моделью ( модель 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 для указания места загрузки постоянного хранилища.

3 голосов
/ 03 июня 2011

Пытаясь обновить модель базовых данных существующего приложения (и перенести устаревшие данные), я просто наткнулся на сценарий, в котором сторонний Framework записывает данные в базу данных приложения. Я получаю эту ошибку: «Не могу найти модель для исходного магазина». Поскольку сторонняя модель не была загружена во время попытки миграции, миграция не удалась.

Я написал этот метод (ниже) во время устранения этой проблемы. Это может быть полезно тем, кто сталкивается с такими проблемами.

- (BOOL) checkModelCompatibilityOfStoreWithURL: (NSURL *) myStoreURL
                                 forModelNamed: (NSString *) myModelName
                                  withBasePath: (NSString *) myBasePath;
{
    NSError * error = nil;
    NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:myStoreURL error:&error];
    if (!storeMeta) {
        NSLog(@"Unable to load store metadata from URL: %@; Error = %@", myStoreURL, error);
        return NO;
    }

    NSString * modelPath = [myBasePath stringByAppendingPathComponent: myModelName];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath: modelPath]) {
        // uh oh
        NSLog(@"Can't find model.");
        return NO;
    }

    NSURL * modelURL = [NSURL fileURLWithPath: modelPath];
    NSManagedObjectModel * model = [[[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL] autorelease];
    BOOL result = [model isConfiguration: nil compatibleWithStoreMetadata: storeMeta];

    NSLog(@"Tested model, %@, is%@ compatible with Database", modelPath, result ? @"" : @" ~not~");

    return result;
}

Этот фрагмент кода получит метаданные магазина.

NSError *error = nil;
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeUrl error:&error];
NSLog(@"%@", [storeMeta objectForKey: @"NSStoreModelVersionHashes"]);

VersionInfo.plist (хранится в комплекте скомпилированного приложения) содержит хэши, связанные с различными объектами в ваших моделях (кодировка base64). Аналогично, столбец BLOB в хранилище данных (Z_METADATA.Z_PLIST) содержит список свойств в двоичном коде, в котором есть хэши (также закодированные в base64) для каждого объекта, связанного с данными.

Метод -entitiesByName в NSManagedObjectModel полезен для сброса сущностей и хэшей, которые существуют в конкретной модели.

1 голос
/ 06 февраля 2019

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

Я удалил приложение из телефона и заново собрал / запустил успешно.

1 голос
/ 20 ноября 2014

У меня была похожая проблема.Я использовал +modelByMergeingModels:, но я не использовал Картографическую модель.Однако объединение моделей не работает с облегченной миграцией данных.

Из документов Apple:

Чтобы выполнить автоматическую облегченную миграцию, Core Data должна иметь возможность найти источник и управляемый объект назначения сама модель s во время выполнения .

Если вы используете +modelByMergeingModels:, чем это используется для модели назначения.Однако Core Data не сможет найти исходную модель.Исходная модель была создана с использованием +modelByMergeingModels: в более старой версии приложения, и Core Data пытается объединить модели, чтобы выяснить исходную модель.

В результате я создал (вручную)новое объединенное .xcdatamodeld путем редактирования XML-файлов моделей, добавления его в проект, удаления отдельных .xcdatamodeld из источников компиляции и вместо использования +modelByMergeingModels: использования NSManagedObjectModel '-initWithContentsOfURL: с URL-адресомновая объединенная модель.Я, вероятно, создам скрипт, который будет автоматически объединять модели в будущем.

...